From 041e33b8b88413bbf1268920846175dc733da565 Mon Sep 17 00:00:00 2001 From: Mohamed El Morabity Date: Mon, 11 Nov 2013 16:12:43 +0100 Subject: [PATCH] media/canalplus.lua: Relicense under AGPLv3+ Notable differences to the 0.4 script: - Supports also d8.tv and d17.tv which share the same video database - Uses the JSON interface provided by Canal+ Differences (:editor:) to the original patch[1]: - Concatenate strings using a table, or "the Lua way"[2] - Remove the old script from the repo test: - Update expected media {title,ID} for the first test URL - Rename test function to `test_media_canalplus' Links: [1]: http://thread.gmane.org/gmane.comp.web.flash.quvi/364 [2]: http://www.luafaq.org/#T1.9 Signed-off-by: Mohamed El Morabity Edited-by: Toni Gundogdu --- share/Makefile.am | 1 + share/lua/website/canalplus.lua | 164 ---------------------------------------- share/media/canalplus.lua | 127 +++++++++++++++++++++++++++++++ tests/media/canalplus.mk | 6 ++ tests/media/media_canalplus.c | 79 +++++++++++++++++++ tests/media/tests.mk | 1 + 6 files changed, 214 insertions(+), 164 deletions(-) delete mode 100644 share/lua/website/canalplus.lua create mode 100644 share/media/canalplus.lua create mode 100644 tests/media/canalplus.mk create mode 100644 tests/media/media_canalplus.c diff --git a/share/Makefile.am b/share/Makefile.am index 7d0fc12..55d3d18 100644 --- a/share/Makefile.am +++ b/share/Makefile.am @@ -46,6 +46,7 @@ dist_media_DATA=\ media/ardmediathek.lua\ media/audioboo.lua\ media/bikeradar.lua\ + media/canalplus.lua\ media/cbsnews.lua\ media/clipfish.lua\ media/collegehumor.lua\ diff --git a/share/lua/website/canalplus.lua b/share/lua/website/canalplus.lua deleted file mode 100644 index 7966c66..0000000 --- a/share/lua/website/canalplus.lua +++ /dev/null @@ -1,164 +0,0 @@ - --- libquvi-scripts --- Copyright (C) 2012 Paul Kocialkowski --- --- This file is part of libquvi-scripts . --- --- This library is free software; you can redistribute it and/or --- modify it under the terms of the GNU Lesser General Public --- License as published by the Free Software Foundation; either --- version 2.1 of the License, or (at your option) any later version. --- --- This library is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --- Lesser General Public License for more details. --- --- You should have received a copy of the GNU Lesser General Public --- License along with this library; if not, write to the Free Software --- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA --- 02110-1301 USA - -local CanalPlus = {} -- Utility functions unique to to this script. - --- Identify the script. -function ident(self) - package.path = self.script_dir .. '/?.lua' - local C = require 'quvi/const' - local r = {} - r.domain = "canalplus%.fr" - r.formats = "default|best" - r.categories = C.proto_rtmp - local U = require 'quvi/util' - r.handles = U.handles(self.page_url, {r.domain}, {"/pid%d", - -- presidentielle2012.canalplus.fr - "/emissions", "/candidats", "/debats", - -- canalstreet.canalplus.fr - "/musique", "/actu", "/humour", "/tendances", "/sport", "/arts", "/danse"}) - - return r -end - --- Query available formats. -function query_formats(self) - local config = CanalPlus.get_config(self) - - if #self.redirect_url >0 then - return self - end - - local U = require 'quvi/util' - local formats = CanalPlus.iter_formats(self, config, U) - - local t = {} - for _,v in pairs(formats) do - table.insert(t, CanalPlus.to_s(v)) - end - - table.sort(t) - self.formats = table.concat(t, "|") - - return self -end - --- Parse media URL. -function parse(self) - self.host_id = 'canalplus' - - local config = CanalPlus.get_config(self) - - if #self.redirect_url >0 then - return self - end - - local U = require 'quvi/util' - local formats = CanalPlus.iter_formats(self, config, U) - local format = U.choose_format(self, formats, - CanalPlus.choose_best, - CanalPlus.choose_default, - CanalPlus.to_s) - or error("unable to choose format") - self.url = {format.url or error("no match: media url")} - - return self -end - --- --- Utility functions --- - -function CanalPlus.get_config(self) - local t = {} - local page = quvi.fetch(self.page_url) - - local u = page:match('"og:video" content="(.-)"') - if u and not u:match('canalplus%.fr') then - self.redirect_url = u -- Media is hosted elsewhere, e.g. YouTube. - return - end - - -- canalplus.fr - self.title = page:match('videoTitre%s-=%s-"(.-)"') - if not self.title then - -- presidentielle2012.canalplus.fr - self.title = page:match('property="og:title"%s+content="(.-)"') - or error('no match: media title') - end - - self.id = page:match('videoId=(%d+)') - or page:match('videoId%s+=%s+"(%d+)"') - or error('no match: media ID') - - local u = "http://service.canal-plus.com/video/rest/getVideosLiees/cplus/" - .. self.id - - return quvi.fetch(u, {fetch_type = 'config'}) -end - -function CanalPlus.iter_formats(self, config, U) - - local id = config:match('(.-)') - if id and id == '-1' then - error('Media is no longer available (expired)') - end - - local p = '' .. self.id .. '' - .. '.-' - .. '.-' - .. '.-' - .. '.-' - .. '.-(.-)<' - .. '.-' - .. '.-(.-)<' - .. '.-(.-)<' - .. '.-(.-)<' - - -- sd = low definition flv - -- hd = high definition flv - -- hq = high definition mp4 - - local thumb,sd_url,hd_url,hq_url = config:match(p) - if not sd_url then error("no match: media url") end - - self.thumbnail_url = thumb or '' - - local t = {} - table.insert(t, {url=sd_url, quality="sd"}) - table.insert(t, {url=hd_url, quality="hd"}) - table.insert(t, {url=hq_url, quality="hq"}) - return t -end - -function CanalPlus.choose_default(t) - return t[1] -- Presume the first to be the 'default'. -end - -function CanalPlus.choose_best(t) - return t[#t] -- Presume the last to be the 'best'. -end - -function CanalPlus.to_s(t) - return t.quality -end - --- vim: set ts=4 sw=4 tw=72 expandtab: diff --git a/share/media/canalplus.lua b/share/media/canalplus.lua new file mode 100644 index 0000000..f9ec4cc --- /dev/null +++ b/share/media/canalplus.lua @@ -0,0 +1,127 @@ +-- libquvi-scripts +-- Copyright (C) 2013 Mohamed El Morabity +-- Copyright (C) 2012 Paul Kocialkowski + +-- This file is part of libquvi-scripts . +-- +-- This program is free software: you can redistribute it and/or +-- modify it under the terms of the GNU Affero General Public +-- License as published by the Free Software Foundation, either +-- version 3 of the License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General +-- Public License along with this program. If not, see +-- . +-- + +local CanalPlus = {} -- Utility functions unique to to this script. + +-- Identify the media script. +function ident(qargs) + return { + can_parse_url = CanalPlus.can_parse_url(qargs), + domains = table.concat({'canalplus.fr', 'd8.tv', 'd17.tv'}, ',') + } +end + +-- Parse media properties. +function parse(qargs) + local J = require 'json' + + local p = quvi.http.fetch(qargs.input_url).data + + -- Make mandatory: needed to fetch the video data JSON. + qargs.id = p:match('videoId%s*=%s*"?(%d+)"?') + or error('no match: media ID') + + -- Get the channel ID. + local channel = p:match('src="http://player%.canalplus%.fr/common/js/' + .. 'canalPlayer%.js%?param=(.-)"') + or error('no match: channel ID') + + -- Fetch the video data JSON. + local t = { + 'http://service.canal-plus.com/video/rest/getVideos/', channel, '/', + qargs.id, '?format=json' + } + + local c = quvi.http.fetch(table.concat(t)).data + j = J.decode(c) + + qargs.thumb_url = j['MEDIA']['IMAGES']['GRAND'] + + qargs.title = j['INFOS']['TITRAGE']['TITRE'] + + qargs.streams = CanalPlus.iter_streams(j) + + return qargs +end + +-- +-- Utility functions +-- + +function CanalPlus.can_parse_url(qargs) + local U = require 'socket.url' + local t = U.parse(qargs.input_url) + if t and t.scheme and t.scheme:lower():match('^http$') + and t.host and (t.host:lower():match('canalplus%.fr$') + or t.host:lower():match('d8%.tv$') + or t.host:lower():match('d17%.tv$')) + and t.path and t.path:lower():match('/pid%d+') then + return true + else + return false + end +end + +function CanalPlus.iter_streams(j) + local S = require 'quvi/stream' + + local d = j['MEDIA']['VIDEOS'] + local r = {} + + for q, v in pairs(d) do + if v ~= '' + -- Some streams have denied accessed, just ignore them. + and q ~= 'HDS' and q ~= 'HLS' and q ~= 'IPHONE' and q ~= 'IPAD' then + local t = S.stream_new(v) + t.nostd = { quality = q } -- Ignored by libquvi. + t.id = CanalPlus.to_id(t) + table.insert(r, t) + end + end + + if #r >1 then + CanalPlus.ch_best(S, r) + end + + return r +end + +function CanalPlus.ch_best(S, t) + -- Available video qualities. + -- HD -> High definition + -- HAUT_DEBIT -> Broadband access + -- BAS_DEBIT -> Dial-up access + -- MOBILE -> Mobile access + local q = { HD = 4, HAUT_DEBIT = 3, BAS_DEBIT = 2, MOBILE = 1 } + local r = t[1] + r.flags.best = true + for _,v in pairs(t) do + if q[v.nostd.quality] > q[r.nostd.quality] then + r = S.swap_best(r, v) + end + end +end + +function CanalPlus.to_id(t) + return t.nostd.quality:lower() +end + +-- vim: set ts=2 sw=2 tw=72 expandtab: diff --git a/tests/media/canalplus.mk b/tests/media/canalplus.mk new file mode 100644 index 0000000..43ae9af --- /dev/null +++ b/tests/media/canalplus.mk @@ -0,0 +1,6 @@ +TEST_PROGS+=media_canalplus +media_canalplus_SOURCES=media/media_canalplus.c +media_canalplus_CPPFLAGS=$(testsuite_cppflags) +media_canalplus_LDFLAGS=$(testsuite_ldflags) +media_canalplus_LDADD=$(testsuite_ldadd) +media_canalplus_CFLAGS=$(AM_CFLAGS) diff --git a/tests/media/media_canalplus.c b/tests/media/media_canalplus.c new file mode 100644 index 0000000..f2f437f --- /dev/null +++ b/tests/media/media_canalplus.c @@ -0,0 +1,79 @@ +/* libquvi-scripts + * Copyright (C) 2013 Mohamed El Morabity + * Copyright (C) 2013 Toni Gundogdu + * + * This file is part of libquvi-scripts . + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General + * Public License along with this program. If not, see + * . + */ + +#include "config.h" + +#include +#include +#include + +#include "tests.h" + +static const gchar *URLs[] = +{ + "http://www.canalplus.fr/c-divertissement/pid1784-c-les-guignols.html?vid=791262", + "http://www.d8.tv/d8-divertissement/pid5200-d8-le-grand-8.html?vid=954696", + "http://www.d17.tv/docs-mags/pid6273-musique.html?vid=933914", + NULL +}; + +static const gchar *TITLEs[] = +{ + "Les Guignols de l'Info du 11/11/13", + "Face à face : Amanda Lear vs Roselyne Bachelot", + "Pink Floyd : Behind «the wall»", + NULL +}; + +static const gchar *IDs[] = +{ + "969879", + "954696", + "933914", + NULL +}; + +static void test_media_canalplus() +{ + struct qm_test_exact_s e; + struct qm_test_opts_s o; + gint i; + + for (i=0; URLs[i] != NULL; ++i) + { + memset(&e, 0, sizeof(e)); + memset(&o, 0, sizeof(o)); + + e.title = TITLEs[i]; + e.id = IDs[i]; + + qm_test(__func__, URLs[i], &e, &o); + } +} + +gint main(gint argc, gchar **argv) +{ + g_test_init(&argc, &argv, NULL); + g_test_add_func("/media/canalplus", test_media_canalplus); + return (g_test_run()); +} + +/* vim: set ts=2 sw=2 tw=72 expandtab: */ diff --git a/tests/media/tests.mk b/tests/media/tests.mk index d82c1e3..e51bd0e 100644 --- a/tests/media/tests.mk +++ b/tests/media/tests.mk @@ -4,6 +4,7 @@ include $(top_srcdir)/tests/media/ardmediathek.mk include $(top_srcdir)/tests/media/arte.mk include $(top_srcdir)/tests/media/audioboo.mk include $(top_srcdir)/tests/media/bikeradar.mk +include $(top_srcdir)/tests/media/canalplus.mk include $(top_srcdir)/tests/media/cbsnews.mk include $(top_srcdir)/tests/media/clipfish.mk include $(top_srcdir)/tests/media/collegehumor.mk -- 2.11.4.GIT