tests: playlist_soundcloud: Update URL
[libquvi-scripts.git] / share / media / ardmediathek.lua
blob7aba3c5bbb631017e6505e829f7716a16fa2bfe3
1 -- libquvi-scripts
2 -- Copyright (C) 2013 Toni Gundogdu <legatvs@gmail.com>
3 -- Copyright (C) 2013 Thomas Weißschuh <thomas@t-8ch.de>
4 --
5 -- This file is part of libquvi-scripts <http://quvi.sourceforge.net/>.
6 --
7 -- This program is free software: you can redistribute it and/or
8 -- modify it under the terms of the GNU Affero General Public
9 -- License as published by the Free Software Foundation, either
10 -- version 3 of the License, or (at your option) any later version.
12 -- This program is distributed in the hope that it will be useful,
13 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
14 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 -- GNU Affero General Public License for more details.
17 -- You should have received a copy of the GNU Affero General
18 -- Public License along with this program. If not, see
19 -- <http://www.gnu.org/licenses/>.
22 local ArdMediathek = {} -- Utility functions unique to to this script.
24 -- Identify the media script.
25 function ident(qargs)
26 return {
27 can_parse_url = ArdMediathek.can_parse_url(qargs),
28 domains = table.concat({'ardmediathek.de'}, ',')
30 end
32 -- Parse the media properties.
33 function parse(qargs)
35 local p = quvi.http.fetch(qargs.input_url).data
37 ArdMediathek.chk_avail(p)
39 qargs.thumb_url = p:match('property="og:image" content="(.-)"') or ''
41 qargs.id = qargs.input_url:match('documentId=(%d+)') or ''
43 qargs.title = ArdMediathek.get_title(p)
45 qargs.streams = ArdMediathek.iter_streams(p)
47 return qargs
48 end
51 -- Utility functions
54 function ArdMediathek.can_parse_url(qargs)
55 local U = require 'socket.url'
56 local t = U.parse(qargs.input_url)
57 if t and t.scheme and t.scheme:lower():match('^http$')
58 and t.host and t.host:lower():match('ardmediathek%.de$')
59 and t.query and t.query:match('^documentId=%d+$')
60 then
61 return true
62 else
63 return false
64 end
65 end
67 function ArdMediathek.get_title(p)
68 return p:match('<meta property="og:title" content="([^"]*)')
69 :gsub('%s*%- %w-$', '') -- remove name of station
70 :gsub('%s*%(FSK.*', '') -- remove FSK nonsense
71 or ''
72 end
74 function ArdMediathek.chk_avail(p)
75 if p:match('<title>ARD Mediathek %- Fehlerseite</title>') then
76 error('an invalid media URL -- the media is no longer available?')
77 end
78 -- Some videos are only scrapable at certain times
79 local s = 'Der Clip ist deshalb nur von (%d%d?) bis (%d%d?) Uhr verfügbar'
80 local from,to = p:match(s)
81 if from and to then
82 local t = {'media available from ', from, ':00 to ', to, ':00 CET only'}
83 error(table.concat(t,''))
84 end
85 end
87 function ArdMediathek.to_container(s)
88 return (s:match('^(...):') or s:match('%.(...)$') or ''):lower()
89 end
91 function ArdMediathek.to_encoding(s)
92 return (s:match('%.(%w+)%.%w+$') or ''):lower()
93 end
95 function ArdMediathek.to_resolution(s)
96 local w,h = s:match('_(%d+)x(%d+)[_%.]')
97 return tonumber(w or 0), tonumber(h or 0)
98 end
100 function ArdMediathek.to_quality(s)
101 local q = (s:match('%.web(%w)%.') or s:match('%.(%w)%.')
102 or s:match('[=%.]Web%-(%w)') -- ".webs", ".s" or "Web-S"
103 or ''):lower()
104 if #q then
105 for k,v in pairs({s='ld', m='md', l='sd', xl='hd'}) do
106 if q == k then
107 return v
111 return q
114 function ArdMediathek.iter_streams(p)
115 local S = require 'quvi/stream'
116 local s = 'mediaCollection%.addMediaStream'
117 .. '%(0, (%d+), "(.-)", "(.-)", "%w+"%);'
118 local r = {}
119 for id,pre,suf in p:gmatch(s) do
120 local u = table.concat({pre,suf},'')
121 u = u:match('^(.-)?') or u -- remove the query string
123 local t = S.stream_new(u)
125 -- Available only for some videos.
126 t.video.width, t.video.height = ArdMediathek.to_resolution(u)
128 t.container = ArdMediathek.to_container(u)
129 t.quality = ArdMediathek.to_quality(u)
131 -- Ignored by libquvi.
132 t.nostd = { internal_id=id }
134 -- Without the 'quality' the stream ID would incomplete.
135 if #t.quality ==0 then
136 t.quality = ArdMediathek.to_encoding(u)
137 else
138 t.video.encoding = ArdMediathek.to_encoding(u)
141 t.id = ArdMediathek.to_id(t)
143 table.insert(r,t)
146 if #r >1 then
147 ArdMediathek.ch_best(S, r)
150 return r
153 function ArdMediathek.ch_best(S, t)
154 local r = t[#t] -- Make the last the best quality.
155 r.flags.best = true
158 function ArdMediathek.to_id(t)
159 return string.format('%s_%s_i%02d%s%s',
160 (#t.quality >0) and t.quality or 'sd',
161 t.container, t.nostd.internal_id,
162 (#t.video.encoding >0) and ('_'..t.video.encoding) or '',
163 (t.video.height >0) and ('_'..t.video.height..'p') or '')
166 -- vim: set ts=2 sw=2 tw=72 expandtab: