appletrailers.lua: Fix script for website changes
authorMarvin Scholz <epirat07@gmail.com>
Mon, 31 Oct 2016 19:51:59 +0000 (20:51 +0100)
committerPierre Ynard <linkfanel@yahoo.fr>
Mon, 31 Oct 2016 19:51:59 +0000 (20:51 +0100)
Fix the Script to work again with the changed
Apple trailers website.

Signed-off-by: Pierre Ynard <linkfanel@yahoo.fr>
share/lua/playlist/appletrailers.lua

index d8c3cc2..c9015ec 100644 (file)
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 --]]
 
--- Probe function.
+-- Probe function
 function probe()
-    return vlc.access == "http"
-        and string.match( vlc.path, "trailers.apple.com" )
-        and string.match( vlc.path, "web.inc" )
+    return (vlc.access == "http" or vlc.access == "https")
+        and string.match( vlc.path, "^trailers%.apple%.com/trailers/.+/.+" )
 end
 
 function find( haystack, needle )
@@ -32,62 +31,113 @@ function find( haystack, needle )
     return r
 end
 
-function sort(a, b)
-    if(a == nil) then return false end
-    if(b == nil) then return false end
+function parse_json(url)
+    vlc.msg.dbg("Trying to parse JSON from " .. url)
+    local json = require ("dkjson")
 
-    local str_a
-    local str_b
+    -- Use vlc.stream to grab a remote json file, place it in a string,
+    -- decode it and return the decoded data.
+    local stream = vlc.stream(url)
+    local string = ""
+    local line   = ""
 
-    if(string.find(a.name, '%(') == 1) then
-        str_a = tonumber(string.sub(a.name, 2, string.find(a.name, 'p') - 1))
-        str_b = tonumber(string.sub(b.name, 2, string.find(b.name, 'p') - 1))
-    else
-        str_a = string.sub(a.name, 1, string.find(a.name, '%(') - 2)
-        str_b = string.sub(b.name, 1, string.find(b.name, '%(') - 2)
-        if(str_a == str_b) then
-            str_a = tonumber(string.sub(a.name, string.len(str_a) + 3, string.find(a.name, 'p', string.len(str_a) + 3) - 1))
-            str_b = tonumber(string.sub(b.name, string.len(str_b) + 3, string.find(b.name, 'p', string.len(str_b) + 3) - 1))
-        end
+    if not stream then return false end
+
+    while true do
+        line = stream:readline()
+        if not line then break end
+
+        string = string .. line
     end
-    if(str_a > str_b) then return false else return true end
+
+    return json.decode(string)
 end
 
 -- Parse function.
 function parse()
+    local video_id = nil
     local playlist = {}
-    local description = ''
-    local art_url = ''
 
-    while true
-    do 
+    while true do
         line = vlc.readline()
         if not line then break end
 
-        if string.match( line, "h3>.-</h3" ) then
-            description = find( line, "h3>(.-)</h3")
-            vlc.msg.dbg(description)
+        if string.match(line, "FilmId%s+=%s+'%d+'") then
+            video_id = find(line, "FilmId%s+=%s+'(%d+)'")
+            vlc.msg.dbg("Found FilmId " .. video_id)
+            break
         end
-        if string.match( line, 'img src=') then
-            for img in string.gmatch(line, '<img src="(http://.*%.jpg)" ') do
-                art_url = img
-            end
-            for i,value in pairs(playlist) do
-                if value.arturl == '' then
-                    playlist[i].arturl = art_url
-                end
-            end
+    end
+
+    -- Found a video id
+    if video_id ~= nil then
+        -- Lookup info from the json endpoint
+        local info = filmid_info(video_id)
+
+        -- Parse data
+        if info["clips"] == nil then
+            vlc.msg.err("Unexpected JSON response from Apple trailers")
+            return playlist
         end
-        if string.match( line, 'class="hd".-%.mov') then
-            for urlline,resolution in string.gmatch(line, 'class="hd".-href="(.-%.mov)".->(%d+.-p)') do
-                urlline = string.gsub( urlline, "_"..resolution, "_h"..resolution )
-                table.insert( playlist, { path = urlline,
-                                          name = description.." "..resolution,
-                                          arturl = art_url,
-                                          options = {":http-user-agent=QuickTime/7.5", ":play-and-pause", ":demux=avformat"} } )
+
+        local movietitle = lookup_keys(info, "details/locale/en/movie_title")
+        local desc       = lookup_keys(info, "details/locale/en/synopsis")
+
+        for _, clip in ipairs(info["clips"]) do
+            local item          = {}
+
+            if clip["title"] == nil then
+                item["name"] = movietitle
+            else
+                item["name"] = movietitle .. " (" .. clip["title"] .. ")"
             end
+            item["path"]        = get_preferred_src(clip)
+            item["artist"]      = clip["artist"]
+            item["arturl"]      = clip["thumb"]
+            item["description"] = desc
+            item["url"]         = vlc.path
+
+            table.insert(playlist, item)
         end
+    else
+        vlc.msg.err("Couldn't extract trailer video URL")
     end
 
     return playlist
 end
+
+-- Request, parse and return the info for a FilmID
+function filmid_info(id)
+    local film_url = "https://trailers.apple.com/trailers/feeds/data/" .. id .. ".json"
+    vlc.msg.dbg("Fetching FilmID info from " .. film_url)
+
+    return parse_json(film_url)
+end
+
+-- Get the user-preferred quality src
+function get_preferred_src(clip)
+    local resolution = vlc.var.inherit(nil, "preferred-resolution")
+    if resolution == -1 then
+        return lookup_keys(clip, "versions/enus/sizes/hd1080/srcAlt")
+    end
+    if resolution >= 1080 then
+        return lookup_keys(clip, "versions/enus/sizes/hd1080/srcAlt")
+    end
+    if resolution >= 720 then
+        return lookup_keys(clip, "versions/enus/sizes/hd720/srcAlt")
+    end
+    return lookup_keys(clip, "versions/enus/sizes/sd/srcAlt")
+end
+
+-- Resolve a "path" in a table or return nil if any of
+-- the keys are not found
+function lookup_keys(table, path)
+    local value = table
+    for token in path:gmatch( "[^/]+" ) do
+        value = value[token]
+        if value == nil then
+            break
+        end
+    end
+    return value
+end