ard.lua: Add Ard.container_from function
[libquvi-scripts.git] / share / lua / website / ard.lua
blobcec5d6944abd168e51457333f1aad357c2abf160
1 -- libquvi-scripts
2 -- Copyright (C) 2013 Thomas Weißschuh
3 --
4 -- This file is part of libquvi-scripts <http://quvi.sourceforge.net/>.
5 --
6 -- This library is free software; you can redistribute it and/or
7 -- modify it under the terms of the GNU Lesser General Public
8 -- License as published by the Free Software Foundation; either
9 -- version 2.1 of the License, or (at your option) any later version.
11 -- This library is distributed in the hope that it will be useful,
12 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
13 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 -- Lesser General Public License for more details.
16 -- You should have received a copy of the GNU Lesser General Public
17 -- License along with this library; if not, write to the Free Software
18 -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 -- 02110-1301 USA
21 local Ard = {}
23 function ident(self)
24 local C = require 'quvi/const'
25 local U = require 'quvi/util'
26 local B = require 'quvi/bit'
27 local r = {}
28 r.domain = 'www%.ardmediathek%.de'
29 r.formats = 'default|best'
30 r.categories = B.bit_or(C.proto_http, C.proto_rtmp)
31 r.handles = U.handles(self.page_url, {r.domain},
32 nil, {"documentId=%d+$"})
33 return r
34 end
36 function query_formats(self)
37 local config = Ard.get_config(self)
38 local formats = Ard.iter_formats(config)
40 local t = {}
41 for _,v in pairs(formats) do
42 table.insert(t, Ard.to_s(v))
43 end
45 table.sort(t)
46 self.formats = table.concat(t, "|")
48 return self
49 end
51 function parse(self)
53 local config = Ard.get_config(self)
54 local Util = require 'quvi/util'
56 Ard.test_availability(config)
58 self.host_id = 'ard'
59 self.title = config:match(
60 '<meta property="og:title" content="([^"]*)'
61 ):gsub(
62 '%s*%- %w-$', '' -- remove name of station
63 ):gsub(
64 '%s*%(FSK.*', '' -- remove FSK nonsense
66 or error('no match: media title')
67 self.thumbnail_url = config:match(
68 '<meta property="og:image" content="([^"]*)'
69 ) or ''
71 local formats = Ard.iter_formats(config)
72 local format = Util.choose_format(self,
73 formats,
74 Ard.choose_best,
75 Ard.choose_default,
76 Ard.to_s)
77 or error('unable to choose format')
79 if not format.url then error('no match: media url') end
80 self.url = { format.url }
82 return self
83 end
85 function Ard.test_availability(page)
86 -- some films are only scrapable at certain times
87 local fsk_pattern =
88 'Der Clip ist deshalb nur von (%d%d?) bis (%d%d?) Uhr verfügbar'
89 local fsk = {}
90 fsk.from, fsk.to = page:match(fsk_pattern)
91 if fsk.from and fsk.to then
92 error('film only available from ' ..fsk.from.. ':00 to '
93 ..fsk.to.. ':00 CET (UTC+2)')
94 end
95 end
97 function Ard.get_config(self)
98 local c = quvi.fetch(self.page_url)
99 self.id = self.page_url:match('documentId=(%d*)')
100 or error('no match: media id')
101 if c:match('<title>ARD Mediathek %- Fehlerseite</title>') then
102 error('invalid URL, maybe the media is no longer available')
105 return c
108 function Ard.choose_best(t)
109 return t[#t] -- return the last from the array
112 function Ard.choose_default(t)
113 return t[1] -- return the first from the array
116 function Ard.to_s(t)
117 return string.format("%s_%s%s%s",
118 (t.quality) and t.quality or 'sd',
119 t.container,
120 (t.encoding) and '_'..t.encoding or '',
121 (t.height) and '_'..t.height or '')
124 function Ard.quality_from(suffix)
125 local q = suffix:match('%.web(%w)%.') or suffix:match('%.(%w)%.')
126 or suffix:match('[=%.]Web%-(%w)') -- .webs. or Web-S or .s
127 if q then
128 q = q:lower()
129 local t = {s='ld', m='md', l='sd', xl='hd'}
130 for k,v in pairs(t) do
131 if q == k then return v end
134 return q
137 function Ard.height_from(suffix)
138 local h = suffix:match('_%d+x(%d+)[_%.]')
139 if h then return h..'p' end
142 function Ard.container_from(suffix)
143 return suffix:match('^(...):') or suffix:match('%.(...)$')
144 or suffix:match('%.(...)$') or 'mp4'
147 function Ard.iter_formats(page)
148 local r = {}
149 local s = 'mediaCollection%.addMediaStream'
150 .. '%(0, %d+, "(.-)", "(.-)", "%w+"%);'
152 for prefix, suffix in page:gmatch(s) do
153 local u = prefix .. suffix
154 -- remove querystring
155 u = u:match('^(.-)?') or u
157 -- .webs. or Web-S or .s.
158 local webx = suffix:match('%.web(%w)%.') or suffix:match('%.(%w)%.')
159 or suffix:match('[=%.]Web%-(%w)')
160 if webx then webx = 'web' .. webx:lower() end
162 local t = {
163 container = Ard.container_from(suffix),
164 encoding = suffix:match('%.(h264)%.'),
165 quality = Ard.quality_from(suffix),
166 height = Ard.height_from(suffix),
167 webx = webx,
168 url = u
170 table.insert(r,t)
173 if #r == 0 then
174 error('no media urls found')
177 return r
180 -- vim: set ts=4 sw=4 sts=4 tw=72 expandtab: