Commit 3e4a7850 authored by Jean-Baptiste Kempf's avatar Jean-Baptiste Kempf
Browse files

Update VLSub.lua

parent 53ac08c9
......@@ -21,27 +21,29 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
--]]
-- Extension description
function descriptor()
return { title = "VLsub" ;
version = "0.8" ;
return { title = "VLsub 0.9" ;
version = "0.9" ;
author = "exebetche" ;
url = 'http://www.opensubtitles.org/';
shortdesc = "VLsub";
description = "<center><b>VLsub</b></center>"
.. "Download subtitles from OpenSubtitles.org" ;
.. "Dowload subtitles from OpenSubtitles.org" ;
capabilities = { "input-listener", "meta-listener" }
}
end
require "os"
-- Global variables
dlg = nil -- Dialog
conflocation = 'subdownloader.conf'
--~ conflocation = 'subdownloader.conf'
url = "http://api.opensubtitles.org/xml-rpc"
progressBarSize = 40
interface_state = 0
result_state = {}
default_language = "eng"
progressBarSize = 70
--~ default_language = "fre"
default_language = nil
refresh_toggle = false
function set_default_language()
if default_language then
......@@ -57,10 +59,10 @@ end
function activate()
vlc.msg.dbg("[VLsub] Welcome")
set_default_language()
create_dialog()
openSub.getFileInfo()
openSub.getMovieInfo()
--~ openSub.request("LogIn")
openSub.request("LogIn")
update_fields()
end
function deactivate()
......@@ -75,19 +77,30 @@ function close()
end
function meta_changed()
update_fields()
end
function input_changed()
--~ Crash !?
--~ wait(3)
--~ update_fields()
end
function update_fields()
openSub.getFileInfo()
openSub.getMovieInfo()
if tmp_method_id == "hash" then
searchHash()
elseif tmp_method_id == "imdb" then
if openSub.movie.name ~= nil then
widget.get("title").input:set_text(openSub.movie.name)
end
if openSub.movie.seasonNumber ~= nil then
widget.get("season").input:set_text(openSub.movie.seasonNumber)
widget.get("episode").input:set_text(openSub.movie.episodeNumber)
end
end
function input_changed()
return false
if openSub.movie.episodeNumber ~= nil then
widget.get("episode").input:set_text(openSub.movie.episodeNumber)
end
end
openSub = {
......@@ -96,12 +109,12 @@ openSub = {
conf = {
url = "http://api.opensubtitles.org/xml-rpc",
userAgentHTTP = "VLSub",
useragent = "VLSub 0.8",
useragent = "VLSub 0.9",
username = "",
password = "",
language = "",
downloadSub = true,
removeTag = true,
removeTag = false,
justgetlink = false
},
session = {
......@@ -123,14 +136,7 @@ openSub = {
movie = {
name = "",
season = "",
episode = "",
imdbid = nil,
imdbidShow = nil,
imdbidEpisode = nil,
imdbRequest = nil,
year = nil,
releasename = nil,
aka = nil
episode = ""
},
sub = {
id = nil,
......@@ -166,8 +172,8 @@ openSub = {
if status == 200 then
response = parse_xmlrpc(responseStr)
--~ vlc.msg.dbg(responseStr)
if (response and response.status == "200 OK") then
vlc.msg.dbg(responseStr)
return openSub.methods[methodName].callback(response)
elseif response then
setError("code "..response.status.."("..status..")")
......@@ -272,32 +278,24 @@ openSub = {
end
end
},
SearchMoviesOnIMDB = {
SearchSubtitles = {
methodName = "SearchSubtitles",
params = function()
openSub.actionLabel = "Searching movie on IMDB"
openSub.actionLabel = "Searching subtitles"
setMessage(openSub.actionLabel..": "..progressBarContent(0))
return {
{ value={ string=openSub.session.token } },
{ value={ string=openSub.movie.imdbRequest } }
}
end,
callback = function(resp)
openSub.itemStore = resp.data
local member = {
{ name="sublanguageid", value={ string=openSub.sub.languageid } },
{ name="query", value={ string=openSub.movie.name } } }
if openSub.itemStore ~= "0" then
return true
else
openSub.itemStore = nil
return false
if openSub.movie.season ~= nil then
table.insert(member, { name="season", value={ string=openSub.movie.season } })
end
if openSub.movie.episode ~= nil then
table.insert(member, { name="episode", value={ string=openSub.movie.episode } })
end
end
},
SearchSubtitlesByIdIMDB = {
methodName = "SearchSubtitles",
params = function()
openSub.actionLabel = "Searching subtitles"
setMessage(openSub.actionLabel..": "..progressBarContent(0))
return {
{ value={ string=openSub.session.token } },
......@@ -306,9 +304,8 @@ openSub = {
data={
value={
struct={
member={
{ name="sublanguageid", value={ string=openSub.sub.languageid } },
{ name="imdbid", value={ string=openSub.movie.imdbid } } }}}}}}}
member=member
}}}}}}
}
end,
callback = function(resp)
......@@ -321,29 +318,6 @@ openSub = {
return false
end
end
},
GetIMDBMovieDetails = {
params = function()
return {
{ value={ string=openSub.session.token } },
{ value={ string=openSub.movie.imdbid } }
}
end,
callback = function(resp)
print(dump_xml(resp))
end
},
IsTVserie = {
methodName = "GetIMDBMovieDetails",
params = function()
return {
{ value={ string=openSub.session.token } },
{ value={ string=openSub.movie.imdbid } }
}
end,
callback = function(resp)
return (string.lower(resp.data.kind)=="tv series")
end
}
},
getInputItem = function()
......@@ -351,10 +325,12 @@ openSub = {
end,
getFileInfo = function()
local item = openSub.getInputItem()
local file = openSub.file
if not item then
file.hasInput = false;
file.cleanName = "";
return false
else
local file = openSub.file
local parsed_uri = vlc.net.url_parse(item:uri())
file.uri = item:uri()
file.protocol = parsed_uri["protocol"]
......@@ -370,11 +346,16 @@ openSub = {
if file.ext == "part" then
file.name, file.ext = string.match(file.name, "^([^/]+)%.([^%.]+)$")
end
file.hasInput = true;
file.cleanName = string.gsub(file.name, "[%._]", " ")
vlc.msg.dbg(file.cleanName)
end
end,
getMovieInfo = function()
if not openSub.file.name then
openSub.movie.name = ""
openSub.movie.seasonNumber = ""
openSub.movie.episodeNumber = ""
return false
end
......@@ -392,6 +373,8 @@ openSub = {
openSub.movie.name = openSub.file.cleanName
openSub.movie.seasonNumber = ""
openSub.movie.episodeNumber = ""
vlc.msg.dbg(openSub.movie.name)
end
end,
getMovieHash = function()
......@@ -423,141 +406,61 @@ openSub = {
return false
end
local i = 1
local a = {0, 0, 0, 0, 0, 0, 0, 0}
local hash = ""
local size = file:seek("end")
file:seek("set", 0)
local bytes = file:read(65536)
file:seek("set", size-65536)
bytes = bytes..file:read("*all")
file:close ()
for b in string.gfind(string.format("%16X ", size), "..") do
d = tonumber(b, 16)
if type(d) ~= "nil" then a[9-i] = d end
i=i+1
end
i = 1
for b in string.gfind(bytes, ".") do
a[i] = a[i] + string.byte(b)
d = math.floor(a[i]/255)
if d>=1 then
a[i] = a[i] - d * 256
if i<8 then a[i+1] = a[i+1] + d end
end
i=i+1
if i==9 then i=1 end
end
for i=8, 1, -1 do
hash = hash..string.format("%02x",a[i])
end
local lo,hi=0,0
for i=1,8192 do
local a,b,c,d = file:read(4):byte(1,4)
lo = lo + a + b*256 + c*65536 + d*16777216
a,b,c,d = file:read(4):byte(1,4)
hi = hi + a + b*256 + c*65536 + d*16777216
while lo>=4294967296 do
lo = lo-4294967296
hi = hi+1
end
while hi>=4294967296 do
hi = hi-4294967296
end
end
local size = file:seek("end", -65536) + 65536
for i=1,8192 do
local a,b,c,d = file:read(4):byte(1,4)
lo = lo + a + b*256 + c*65536 + d*16777216
a,b,c,d = file:read(4):byte(1,4)
hi = hi + a + b*256 + c*65536 + d*16777216
while lo>=4294967296 do
lo = lo-4294967296
hi = hi+1
end
while hi>=4294967296 do
hi = hi-4294967296
end
end
lo = lo + size
while lo>=4294967296 do
lo = lo-4294967296
hi = hi+1
end
while hi>=4294967296 do
hi = hi-4294967296
end
openSub.file.bytesize = size
openSub.file.hash = hash
openSub.file.hash = string.format("%08x%08x", hi,lo)
return true
end,
getImdbEpisodeId = function(season, episode)
openSub.actionLabel = "Searching episode id on IMDB"
setMessage(openSub.actionLabel..": "..progressBarContent(0))
local IMDBurl = "http://www.imdb.com/title/tt"..openSub.movie.imdbid.."/episodes/_ajax?season="..season
local host, path = parse_url(IMDBurl)
local stream = vlc.stream(IMDBurl)
local data = ""
while data do
data = stream:read(65536)
local id = string.match(data, 'data%-const="tt(%d+)"[^>]+>\r?\n<img[^>]+>\r?\n<div> S'..season..', Ep'..episode)
return id
end
return false
end,
getImdbEpisodeIdYQL = function(season, episode)
openSub.actionLabel = "Searching episode on IMDB"
setMessage(openSub.actionLabel..": "..progressBarContent(0))
local url = "http://pipes.yahoo.com/pipes/pipe.run?_id=5f525406f2b2b376eeb20b97a216bcb1&_render=json&imdbid="..openSub.movie.imdbid.."&season="..season.."&episode="..episode
local host, path = parse_url(url)
local header = {
"GET "..path.." HTTP/1.1",
"Host: "..host,
"User-Agent: "..openSub.conf.userAgentHTTP,
"",
""
}
local request = table.concat(header, "\r\n")
local fd = vlc.net.connect_tcp(host, 80)
local data = ""
if fd >= 0 then
local pollfds = {}
pollfds[fd] = vlc.net.POLLIN
vlc.net.send(fd, request)
vlc.net.poll(pollfds)
data = vlc.net.recv(fd, 2048)
print(data)
end
setMessage(openSub.actionLabel..": "..progressBarContent(100))
local id = string.match(data, '"content":"(%d+)"')
return id
end,
getImdbEpisodeIdGoogle = function(season, episode, title)
openSub.actionLabel = "Searching episode on IMDB"
setMessage(openSub.actionLabel..": "..progressBarContent(0))
local query = 'site:imdb.com tv episode "'..title..'" (#'..season..'.'..episode..')'
local url = "https://www.google.com/uds/GwebSearch?hl=fr&source=gsc&gss=.com&gl=www.google.com&context=1&key=notsupplied&v=1.0&&q="..vlc.strings.encode_uri_component(query)
local host, path = parse_url(url)
local header = {
"GET "..path.." HTTP/1.1",
"Host: "..host,
"User-Agent: "..openSub.conf.userAgentHTTP,
"",
""
}
local request = table.concat(header, "\r\n")
local fd = vlc.net.connect_tcp(host, 80)
local data = ""
if fd >= 0 then
local pollfds = {}
pollfds[fd] = vlc.net.POLLIN
vlc.net.send(fd, request)
vlc.net.poll(pollfds)
data = vlc.net.recv(fd, 2048)
--print(data)
end
setMessage(openSub.actionLabel..": "..progressBarContent(100))
local id = string.match(data, '"url":"http://www.imdb.com/title/tt(%d+)/"')
return id
end,
loadSubtitles = function(url, fileDir, SubFileName, target)
loadSubtitles = function(url, SubFileName, target)
openSub.actionLabel = "Downloading subtitle"
setMessage(openSub.actionLabel..": "..progressBarContent(0))
local subfileURI = nil
local resp = get(url)
local subfileURI = ""
if resp then
local tmpFileName = fileDir..SubFileName..".zip"
local tmpFileName = openSub.file.dir..SubFileName..".zip"
subfileURI = "zip://"..make_uri(tmpFileName, true).."!/"..SubFileName
local tmpFile = assert(io.open(tmpFileName, "wb"))
tmpFile:write(resp)
tmpFile:flush()
tmpFile:close()
subfileURI = "zip://"..make_uri(tmpFileName, true).."!/"..SubFileName
if target then
local stream = vlc.stream(subfileURI)
local data = ""
......@@ -571,18 +474,20 @@ openSub = {
end
data = stream:readline()
end
subfile:close()
subfile:flush()
subfile:close()
stream = nil
collectgarbage()
subfileURI = make_uri(target, true)
end
subfileURI = make_uri(target, true)
collectgarbage() -- force gargabe collection in order to close the opened stream
os.remove(tmpFileName)
os.remove(tmpFileName)
end
local item = vlc.item or vlc.input.item()
if item then
if vlc.item or vlc.input.item() then
vlc.msg.dbg("Adding subtitle :" .. subfileURI)
vlc.input.add_subtitle(subfileURI)
setMessage("Success: Subtitles loaded.")
else
setError("No current input, unable to add subtitles "..target)
end
......@@ -590,8 +495,7 @@ openSub = {
}
function make_uri(str, encode)
local iswindowPath = string.match(str, "^%a:/.+$")
-- vlc.msg.dbg(iswindowPath)
local windowdrive = string.match(str, "^(%a:/).+$")
if encode then
local encodedPath = ""
for w in string.gmatch(str, "/([^/]+)") do
......@@ -600,139 +504,58 @@ function make_uri(str, encode)
end
str = encodedPath
end
if iswindowPath then
return "file:///"..str
if windowdrive then
return "file:///"..windowdrive..str
else
return "file://"..str
end
end
function searchHash()
if not hasAssociatedResult() then
openSub.sub.languageid = languages[widget.getVal("language")][2]
openSub.getMovieHash()
associatedResult()
if openSub.file.hash then
openSub.request("SearchSubtitlesByHash")
display_subtitles()
end
else
local selection = widget.getVal("hashmainlist")
if #selection > 0 then
download_subtitles(selection)
end
function download_selection()
local selection = widget.getVal("mainlist")
if #selection > 0 and openSub.itemStore then
download_subtitles(selection)
end
end
function searchIMBD()
local title = trim(widget.getVal("title"))
local old_title = trim(widget.get("title").value)
local season = tonumber(widget.getVal("season"))
local old_season = tonumber(widget.get("season").value)
local episode = tonumber(widget.getVal("episode"))
local old_episode = tonumber(widget.get("episode").value)
local language = languages[widget.getVal("language")][2]
local selection = widget.getVal("imdbmainlist")
local sel = (#selection > 0)
local newTitle = (title ~= old_title)
local newEpisode = (season ~= old_season or episode ~= old_episode)
local newLanguage = (language ~= openSub.sub.languageid)
local movie = openSub.movie
local imdbResults = {}
widget.get("title").value = title
widget.get("season").value = season
widget.get("episode").value = episode
openSub.sub.languageid = language
if newTitle then
movie.imdbRequest = title
movie.imdbid = nil
movie.imdbidShow = nil
if openSub.request("SearchMoviesOnIMDB") then -- search exact match
local lowerTitle = string.lower(title)
local itemTitle = ""
for i, item in ipairs(openSub.itemStore) do
-- itemTitle = string.match(item.title, "[%s\"]*([^%(\"]*)[%s\"']*%(?")
item.cleanTitle = string.match(item.title, "[%s\"]*([^%(\"]*)[%s\"']*%(?")
-- vlc.msg.dbg(itemTitle)
--[[if string.lower(itemTitle) == lowerTitle then
movie.imdbid = item.id
break
end]]
table.insert(imdbResults, item.title)
end
if not movie.imdbid then
widget.setVal("imdbmainlist")
widget.setVal("imdbmainlist", imdbResults)
end
end
end
function searchHash()
openSub.sub.languageid = languages[widget.getVal("language")][2]
if not movie.imdbid and sel then
local index = selection[1][1]
local item = openSub.itemStore[index]
movie.imdbid = item.id
movie.title = item.cleanTitle
movie.imdbidShow = movie.imdbid
newEpisode = true
message = widget.get("message")
if message.display == "none" then
message.display = "block"
widget.set_interface(interface)
end
if movie.imdbid then
if season and episode and (newTitle or newEpisode) then
if not newTitle then
movie.imdbid = movie.imdbidShow
end
movie.imdbidEpisode = openSub.getImdbEpisodeIdGoogle(season, episode, movie.title)
-- movie.imdbidEpisode = openSub.getImdbEpisodeId(season, episode)
openSub.getMovieHash()
if movie.imdbidEpisode then
vlc.msg.dbg("Episode imdbid: "..movie.imdbidEpisode)
movie.imdbidShow = movie.imdbid
movie.imdbid = movie.imdbidEpisode
elseif openSub.request("IsTVserie") then
movie.imdbidEpisode = openSub.getImdbEpisodeIdYQL(season, episode)
if movie.imdbidEpisode then
movie.imdbidShow = movie.imdbid
movie.imdbid = movie.imdbidEpisode
else
setError("Season/episode don't match for this title")
end
else
setError("Title not referenced as a TV serie on IMDB")
--~ -- , choose an other one and/or empty episode/season field")
widget.setVal("imdbmainlist", imdbResults)
end
end
if newTitle or newEpisode or newLanguage then
openSub.request("SearchSubtitlesByIdIMDB")
display_subtitles()
elseif sel and openSub.itemStore then
download_subtitles(selection)
end
if openSub.file.hash then
openSub.request("SearchSubtitlesByHash")
display_subtitles()
end
end
function associatedResult()
local item = openSub.getInputItem()
if not item then return false end
result_state[tmp_method_id] = item:uri()