]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/imdb.rb
imdb plugin: handle double-redirection and other charset-related issues
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / imdb.rb
1 #-- vim:sw=2:et
2 #++
3 #
4 # :title: IMDB plugin for rbot
5 #
6 # Author:: Arnaud Cornet <arnaud.cornet@gmail.com>
7 # Copyright:: (C) 2005 Arnaud Cornet
8 # License:: MIT license
9 #
10 # Notes by Giuseppe Bilotta:
11 # TODO return more than one match (configurable)
12
13 require 'uri/common'
14
15 class Imdb
16   def initialize(bot)
17     @bot = bot
18   end
19
20   def search(rawstr)
21     str = URI.escape(rawstr) << ";site=aka"
22     return do_search(str)
23   end
24
25   def do_search(str)
26     resp = nil
27     begin
28       resp = @bot.httputil.get_response("http://us.imdb.com/find?q=#{str}",
29                                         :max_redir => -1)
30     rescue Exception => e
31       error e.message
32       warning e.backtrace.join("\n")
33       return nil
34     end
35
36     if resp.code == "200"
37       m = /<a href="(\/(?:title|name)\/(?:tt|nm)[0-9]+\/?)[^"]*"(?:[^>]*)>(?:[^<]*)<\/a>/.match(resp.body)
38       if m
39         url = m[1]
40         return url
41       end
42     elsif resp.code == "302"
43       new_loc = resp['location'].gsub(/http:\/\/us.imdb.com/, "")
44       if new_loc.match(/\/find\?q=(.*)/)
45         return do_search($1)
46       else
47         return new_loc.gsub(/\?.*/, "")
48       end
49     end
50     return nil
51   end
52
53   def info(rawstr)
54     sr = search(rawstr)
55     if !sr
56       debug "IMDB: search returned NIL"
57       return nil
58     end
59     type = sr.match(/^\/([^\/]+)\//)[1].downcase.intern rescue nil
60     case type
61     when :title
62       return info_title(sr)
63     when :name
64       return info_name(sr)
65     else
66       return "#{sr}"
67     end
68   end
69
70   def grab_info(info, body)
71     /<div class="info">\s+<h5>#{info}:<\/h5>\s+(.*?)<\/div>/mi.match(body)[1] rescue nil
72   end
73
74   def info_title(sr)
75     resp = nil
76     begin
77       resp = @bot.httputil.get_response('http://us.imdb.com' + sr,
78                                         :max_redir => -1)
79     rescue Exception => e
80       error e.message
81       warning e.backtrace.join("\n")
82       return nil
83     end
84
85     if resp.code == "200"
86       m = /<title>([^<]*)<\/title>/.match(resp.body)
87       return nil if !m
88       title = Utils.decode_html_entities(m[1])
89
90       m = /<b>([0-9.]+)\/10<\/b>\n?\r?\s+<small>\(<a href="ratings">([0-9,]+) votes?<\/a>\)<\/small>/.match(resp.body)
91       return nil if !m
92       score = m[1]
93       votes = m[2]
94
95       plot = nil
96       data = grab_info(/Plot (?:Outline|Summary)/, resp.body)
97       if data
98         plot = "Plot: #{data.ircify_html.gsub(/\s+more$/,'')}"
99       end
100
101       genre = Array.new
102       resp.body.scan(/<a href="\/Sections\/Genres\/[^\/]+\/">([^<]+)<\/a>/) do |gnr|
103         genre << gnr
104       end
105       info = "#{title} : http://us.imdb.com#{sr}\n"
106       info << "Ratings: #{score}/10 (#{votes} voters). Genre: #{genre.join('/')}\n"
107       info << plot if plot
108       return info
109     end
110     return nil
111   end
112
113   def info_name(sr)
114     resp = nil
115     begin
116       resp = @bot.httputil.get_response('http://us.imdb.com' + sr,
117                                         :max_redir => -1)
118     rescue Exception => e
119       error e.message
120       warning e.backtrace.join("\n")
121       return nil
122     end
123
124     if resp.code == "200"
125       m = /<title>([^<]*)<\/title>/.match(resp.body)
126       return nil if !m
127       name = Utils.decode_html_entities(m[1])
128
129       birth = nil
130       data = grab_info("Date of Birth", resp.body)
131       if data
132         birth = "Birth: #{data.ircify_html.gsub(/\s+more$/,'')}"
133       end
134
135       death = nil
136       data = grab_info("Date of Death", resp.body)
137       if data
138         death = "Death: #{data.ircify_html.gsub(/\s+more$/,'')}"
139       end
140
141       awards = nil
142       data = grab_info("Awards", resp.body)
143       if data
144         awards = "Awards: #{data.ircify_html.gsub(/\s+more$/,'')}"
145       end
146
147       info = "#{name} : http://us.imdb.com#{sr}\n"
148       info << [birth, death].compact.join('. ') << "\n"
149       info << awards if awards
150       return info
151
152     end
153     return nil
154   end
155 end
156
157 class ImdbPlugin < Plugin
158   def help(plugin, topic="")
159     "imdb <string> => search http://www.imdb.org for <string>"
160   end
161
162   def imdb(m, params)
163     what = params[:what].to_s
164     i = Imdb.new(@bot)
165     info = i.info(what)
166     if !info
167       m.reply "Nothing found for #{what}"
168       return nil
169     end
170     m.reply info
171   end
172 end
173
174 plugin = ImdbPlugin.new
175 plugin.map "imdb *what"
176