Commit 50c1c958 authored by Jean-Philippe André's avatar Jean-Philippe André Committed by Jean-Baptiste Kempf

imdb.lua: Redesign, fix some bugs

(cherry picked from commit ac07c98252cdcbacf3340f2b5522f808169331dd)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 9f5560ee
...@@ -20,11 +20,25 @@ ...@@ -20,11 +20,25 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
--]] --]]
dlg = nil -- TODO: Use simplexml module to simplify parsing
txt = nil
-- Global variables
url = nil -- string
title = nil -- string
titles = {} -- table, see code below
-- Some global variables: widgets
dlg = nil -- dialog
txt = nil -- text field
list = nil -- list widget
button_open = nil -- button widget
html = nil -- rich text (HTML) widget
waitlbl = nil -- text label widget
-- Script descriptor, called when the extensions are scanned
function descriptor() function descriptor()
return { title = "IMDb - The Internet Movie Database" ; return { title = "IMDb - The Internet Movie Database" ;
version = "0.1" ; version = "1.0" ;
author = "Jean-Philippe André" ; author = "Jean-Philippe André" ;
url = 'http://www.imdb.org/'; url = 'http://www.imdb.org/';
shortdesc = "The Internet Movie Database"; shortdesc = "The Internet Movie Database";
...@@ -36,93 +50,174 @@ function descriptor() ...@@ -36,93 +50,174 @@ function descriptor()
capabilities = { "input-listener" } } capabilities = { "input-listener" } }
end end
-- Remove trailing & leading spaces
function trim(str)
if not str then return "" end
return string.gsub(str, "^%s*(.*)+%s$", "%1")
end
-- Update title text field. Removes file extensions. -- Update title text field. Removes file extensions.
function update_title() function update_title()
local item = vlc.input.item() local item = vlc.input.item()
local title = item and item:name() local name = item and item:name()
if title ~= nil then if name ~= nil then
title = string.gsub(title, "(.*)(%.%w+)$", "%1") name = string.gsub(name, "(.*)(%.%w+)$", "%1")
end end
if title ~= nil then if name ~= nil then
txt:set_text(title) txt:set_text(trim(name))
end end
end end
-- Function called when the input (media being read) changes
function input_changed() function input_changed()
update_title() update_title()
end end
function create_dialog() -- First function to be called when the extension is activated
dlg = vlc.dialog("IMDb Search")
dlg:add_label("The Internet Movie Database", 1, 1, 4, 1)
dlg:add_label("<b>Movie Title</b>", 1, 2, 1, 1)
local item = vlc.input.item()
txt = dlg:add_text_input(item and item:name() or "", 2, 2, 1, 1)
dlg:add_button("Okay", click_okay, 3, 2, 1, 1)
dlg:add_button("*", update_title, 4, 2, 1, 1)
dlg:show() -- Show, if not already visible
end
function activate() function activate()
create_dialog() create_dialog()
end end
-- This function is called when the extension is disabled
function deactivate() function deactivate()
end end
-- Create the main dialog with a simple search bar
function create_dialog()
dlg = vlc.dialog("IMDb")
dlg:add_label("<b>Movie Title:</b>", 1, 1, 1, 1)
local item = vlc.input.item()
txt = dlg:add_text_input(item and item:name() or "", 2, 1, 1, 1)
dlg:add_button("Search", click_okay, 3, 1, 1, 1)
-- Show, if not already visible
dlg:show()
end
-- Dialog closed -- Dialog closed
function close() function close()
-- Deactivate this extension -- Deactivate this extension
vlc.deactivate() vlc.deactivate()
end end
-- Some global variables: widgets -- Called when the user presses the "Search" button
list = nil
button_open = nil
titles = nil
html = nil
function click_okay() function click_okay()
vlc.msg.dbg("Searching for " .. txt:get_text() .. " on IMDb") vlc.msg.dbg("[IMDb] Searching for " .. txt:get_text())
-- Search IMDb: build URL
title = string.gsub(string.gsub(txt:get_text(), "[%p%s%c]", "+"), "%++", " ")
url = "http://www.imdb.com/find?s=all&q=" .. string.gsub(title, " ", "+")
-- Recreate dialog structure: delete useless widgets
if html then if html then
dlg:del_widget(html) dlg:del_widget(html)
html = nil html = nil
end end
if not list then if list then
list = dlg:add_list(1, 3, 4, 1) dlg:del_widget(list)
button_open = dlg:add_button("Open", click_open, 1, 4, 4, 1) dlg:del_widget(button_open)
list = nil
button_open = nil
end end
-- Clear previous results -- Ask the user to wait some time...
list:clear() local waitmsg = 'Searching for <a href="' .. url .. '">' .. title .. "</a> on IMDb..."
if not waitlbl then
waitlbl = dlg:add_label(waitmsg, 1, 2, 3, 1)
else
waitlbl:set_text(waitmsg)
end
dlg:update()
-- Search IMDb -- Download the data
local url = "http://www.imdb.com/find?s=all&q=" local s, msg = vlc.stream(url)
local title = string.gsub(txt:get_text(), " ", "+")
local s, msg = vlc.stream(url .. title)
if not s then if not s then
vlc.msg.warn(msg) vlc.msg.warn("[IMDb] " .. msg)
waitlbl:set_text('Sorry, an error occured while searching for <a href="'
.. url .. '">' .. title .. "</a>.<br />Please try again later.")
return return
end end
-- Fetch HTML data -- Fetch HTML data
local data = s:read(65000) local data = s:read(65000)
if not data then
vlc.msg.warn("[IMDb] Not data received!")
waitlbl:set_text('Sorry, an error occured while searching for <a href="'
.. url .. '">' .. title .. "</a>.<br />Please try again later.")
return
end
-- Probe result & parse it
if string.find(data, "<h6>Overview</h6>") then
-- We found a direct match
parse_moviepage(data)
else
-- We have a list of results to parse
parse_resultspage(data)
end
end
-- Called when clicked on the "Open" button
function click_open()
-- Get user selection
selection = list:get_selection()
if not selection then return end
local sel = nil
for idx, selectedItem in pairs(selection) do
sel = idx
break
end
if not sel then return end
local imdbID = titles[sel].id
-- Update information message
url = "http://www.imdb.org/title/" .. imdbID .. "/"
title = titles[sel].title
dlg:del_widget(list)
dlg:del_widget(button_open)
list = nil
button_open = nil
waitlbl:set_text("Loading IMDb page for <a href=\"" .. url .. "\">" .. title .. "</a>.")
dlg:update()
local s, msg = vlc.stream(url)
if not s then
waitlbl:set_text('Sorry, an error occured while looking for <a href="'
.. url .. '">' .. title .. "</a>.")
vlc.msg.warn("[IMDb] " .. msg)
return
end
data = s:read(65000)
if data and string.find(data, "<h6>Overview</h6>") then
parse_moviepage(data)
else
waitlbl:set_text('Sorry, no results found for <a href="'
.. url .. '">' .. title .. "</a>.")
end
end
-- Parse the results page and find titles, years & URL's
function parse_resultspage(data)
vlc.msg.dbg("[IMDb] Analysing results page")
-- Find titles -- Find titles
titles = {} titles = {}
local count = 0 local count = 0
idxEnd = 1 local idxEnd = 1
while idxEnd ~= nil do while idxEnd ~= nil do
-- Find title types -- Find title types
local titleType = nil
_, idxEnd, titleType = string.find(data, "<b>([^<]*Titles[^<]*)</b>", idxEnd) _, idxEnd, titleType = string.find(data, "<b>([^<]*Titles[^<]*)</b>", idxEnd)
_, _, nextTitle = string.find(data, "<b>([^<]*Titles[^<]*)</b>", idxEnd) local _, _, nextTitle = string.find(data, "<b>([^<]*Titles[^<]*)</b>", idxEnd)
if not titleType then if not titleType then
break break
else else
-- Find current scope -- Find current scope
local table = nil
if not nextTitle then if not nextTitle then
_, _, table = string.find(data, "<table>(.*)</table>", idxEnd) _, _, table = string.find(data, "<table>(.*)</table>", idxEnd)
else else
...@@ -130,63 +225,59 @@ function click_okay() ...@@ -130,63 +225,59 @@ function click_okay()
nextTitle = string.gsub(nextTitle, "%)", "%%)") nextTitle = string.gsub(nextTitle, "%)", "%%)")
_, _, table = string.find(data, "<table>(.*)</table>.*"..nextTitle, idxEnd) _, _, table = string.find(data, "<table>(.*)</table>.*"..nextTitle, idxEnd)
end end
-- Find all titles in this scope
if not table then break end if not table then break end
pos = 0 local pos = 0
local thistitle = nil
-- Find all titles in this scope
while pos ~= nil do while pos ~= nil do
_, _, link = string.find(table, "<a href=\"([^\"]+title[^\"]+)\"", pos) local _, _, link = string.find(table, "<a href=\"([^\"]+title[^\"]+)\"", pos)
if not link then break end -- this would not be normal behavior... if not link then break end -- this would not be normal behavior...
_, pos, title = string.find(table, "<a href=\"" .. link .. "\"[^>]*>([^<]+)</a>", pos) _, pos, thistitle = string.find(table, "<a href=\"" .. link .. "\"[^>]*>([^<]+)</a>", pos)
if not title then break end -- this would not be normal behavior... if not thistitle then break end -- this would not be normal behavior...
_, _, year = string.find(table, "\((%d+)\)", pos) local _, _, year = string.find(table, "\((%d+)\)", pos)
-- Add this title to the list -- Add this title to the list
count = count + 1 count = count + 1
_, _, imdbID = string.find(link, "/([^/]+)/$") local _, _, imdbID = string.find(link, "/([^/]+)/$")
title = replace_html_chars(title) thistitle = replace_html_chars(thistitle)
titles[count] = { id = imdbID ; title = title ; year = year ; link = link } titles[count] = { id = imdbID ; title = thistitle ; year = year ; link = link }
end end
end end
end end
for idx, title in ipairs(titles) do -- Did we find anything at all?
list:add_value("[" .. title.id .. "] " .. title.title .. " (" .. title.year .. ")", idx) if not count or count == 0 then
end waitlbl:set_text('Sorry, no results found for <a href="'
end .. url .. '">' .. title .. "</a>.")
return
function click_open()
selection = list:get_selection()
if not selection then return 1 end
if not html then
html = dlg:add_html("Loading IMDb page...", 1, 3, 4, 1)
-- userLink = dlg:add_label("", 1, 4, 5, 1)
end end
dlg:del_widget(list) -- Sounds good, we found some results, let's display them
dlg:del_widget(button_open) waitlbl:set_text(count .. " results found for <a href=\"" .. url .. "\">" .. title .. "</a>.")
list = nil list = dlg:add_list(1, 3, 3, 1)
button_open = nil button_open = dlg:add_button("Open", click_open, 3, 4, 1, 1)
local sel = nil for idx, title in ipairs(titles) do
for idx, selectedItem in pairs(selection) do --list:add_value("[" .. title.id .. "] " .. title.title .. " (" .. title.year .. ")", idx)
sel = idx list:add_value(title.title .. " (" .. title.year .. ")", idx)
break
end end
imdbID = titles[sel].id end
url = "http://www.imdb.org/title/" .. imdbID .. "/"
-- userLink:set_text("<a href=\"url\">" .. url .. "</a>") -- Parse a movie description page
function parse_moviepage(data)
-- Title & year
title = string.gsub(data, "^.*<title>(.*)</title>.*$", "%1")
local text = "<h1>" .. title .. "</h1>"
text = text .. "<h2>Overview</h2><table>"
local s, msg = vlc.stream(url) -- Real URL
if not s then url = string.gsub(data, "^.*<link rel=\"canonical\" href=\"([^\"]+)\".*$", "%1")
vlc.msg.warn(msg) local imdbID = string.gsub(url, "^.*/title/([^/]+)/.*$", "%1")
return if imdbID then
url = "http://www.imdb.org/title/" .. imdbID .. "/"
end end
data = s:read(65000)
text = "<h1>" .. titles[sel].title .. " (" .. titles[sel].year .. ")</h1>"
text = text .. "<h2>Overview</h2><table>"
-- Director -- Director
local director = nil local director = nil
_, nextIdx, _ = string.find(data, "<div id=\"director-info\"", 1, true) _, nextIdx, _ = string.find(data, "<div id=\"director-info\"", 1, true)
...@@ -213,7 +304,7 @@ function click_open() ...@@ -213,7 +304,7 @@ function click_open()
-- List main actors -- List main actors
local actors = "<tr><td><b>Cast</b></td>" local actors = "<tr><td><b>Cast</b></td>"
first = true local first = true
for nm, char in string.gmatch(data, "<td class=\"nm\"><a[^>]+>([%w%s]+)</a></td><td class=\"ddd\"> ... </td><td class=\"char\"><a[^>]+>([%w%s]+)</a>") do for nm, char in string.gmatch(data, "<td class=\"nm\"><a[^>]+>([%w%s]+)</a></td><td class=\"ddd\"> ... </td><td class=\"char\"><a[^>]+>([%w%s]+)</a>") do
if not first then if not first then
actors = actors .. "<tr><td />" actors = actors .. "<tr><td />"
...@@ -223,13 +314,21 @@ function click_open() ...@@ -223,13 +314,21 @@ function click_open()
end end
text = text .. actors .. "</table>" text = text .. actors .. "</table>"
waitlbl:set_text("<center><a href=\"" .. url .. "\">" .. title .. "</a></center>")
if list then
dlg:del_widget(list)
dlg:del_widget(button_open)
end
html = dlg:add_html(text .. "<br />Loading summary...", 1, 3, 3, 1)
dlg:update()
text = text .. "<h2>Plot Summary</h2>" text = text .. "<h2>Plot Summary</h2>"
s, msg = vlc.stream(url .. "plotsummary") local s, msg = vlc.stream(url .. "plotsummary")
if not s then if not s then
vlc.msg.warn(msg) vlc.msg.warn("[IMDb] " .. msg)
return return
end end
data = s:read(65000) local data = s:read(65000)
-- We read only the first summary -- We read only the first summary
_, _, summary = string.find(data, "<p class=\"plotpar\">([^<]+)") _, _, summary = string.find(data, "<p class=\"plotpar\">([^<]+)")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment