* use of browser 2 * choose between videos version (ie: subtitles or not) * support of cinema.arte.tv
190 lines
8.1 KiB
Python
190 lines
8.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright(C) 2010-2011 Romain Bignon
|
|
#
|
|
# This file is part of weboob.
|
|
#
|
|
# weboob 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.
|
|
#
|
|
# weboob 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 weboob. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import re
|
|
|
|
from weboob.capabilities.collection import Collection
|
|
from weboob.capabilities.base import UserError
|
|
from weboob.capabilities import NotAvailable
|
|
|
|
from weboob.browser import PagesBrowser, URL
|
|
from .pages import VideosListPage, VideoPage, ArteJsonPage
|
|
from .video import VERSION_VIDEO, LANG, QUALITY, FORMATS, SITE
|
|
|
|
|
|
__all__ = ['ArteBrowser']
|
|
|
|
|
|
class ArteBrowser(PagesBrowser):
|
|
BASEURL = 'http://arte.tv/'
|
|
|
|
webservice = URL('papi/tvguide/(?P<class_name>.*)/(?P<method_name>.*)/(?P<parameters>.*).json',
|
|
'http://(?P<__site>.*).arte.tv/(?P<_lang>\w{2})/player/(?P<_id>.*)',
|
|
'https://api.arte.tv/api/player/v1/config/(?P<__lang>\w{2})/(?P<vid>.*)\?vector=(?P<___site>.*)',
|
|
ArteJsonPage)
|
|
videos_list = URL('http://(?P<site>.*).arte.tv/(?P<lang>\w{2})/?(?P<cat>.*?)', VideosListPage)
|
|
video_page = URL('http://(?P<_site>.*).arte.tv/(?P<id>.+)', VideoPage)
|
|
|
|
def __init__(self, lang, quality, order, format, version, *args, **kwargs):
|
|
self.order = order
|
|
self.lang = (value for key, value in LANG.items if key == lang).next()
|
|
self.version = (value for key, value in VERSION_VIDEO.items
|
|
if self.lang.get('label') in value.keys() and version == key).next()
|
|
self.quality = (value for key, value in QUALITY.items if key == quality).next()
|
|
self.format = format
|
|
|
|
if self.lang.get('label') not in self.version.keys():
|
|
raise UserError('%s is not available for %s' % (self.lang.get('label'), version))
|
|
|
|
PagesBrowser.__init__(self, *args, **kwargs)
|
|
|
|
def search_videos(self, pattern):
|
|
class_name = 'videos/plus7'
|
|
method_name = 'search'
|
|
parameters = '/'.join([self.lang.get('webservice'), 'L1', pattern.encode('utf-8'), 'ALL', 'ALL', '-1',
|
|
self.order, '10', '0'])
|
|
return self.webservice.go(class_name=class_name, method_name=method_name, parameters=parameters).iter_videos()
|
|
|
|
def get_video(self, id, video=None):
|
|
class_name = 'videos'
|
|
method_name = 'stream/player'
|
|
parameters = '/'.join([self.lang.get('webservice'), id, 'ALL', 'ALL'])
|
|
video = self.webservice.go(class_name=class_name,
|
|
method_name=method_name,
|
|
parameters=parameters).get_video(obj=video)
|
|
video.ext, video.url = self.get_url()
|
|
return video
|
|
|
|
def get_url(self):
|
|
url = self.page.get_video_url(self.quality, self.format, self.version.get(self.lang.get('label')),
|
|
self.lang.get('version'))
|
|
if format == FORMATS.HLS:
|
|
ext = u'm3u8'
|
|
url = self.get_m3u8_link(url)
|
|
else:
|
|
ext = u'mp4'
|
|
url = url
|
|
return ext, url
|
|
|
|
def get_m3u8_link(self, url):
|
|
r = self.openurl(url)
|
|
baseurl = url.rpartition('/')[0]
|
|
|
|
links_by_quality = []
|
|
for line in r.readlines():
|
|
if not line.startswith('#'):
|
|
links_by_quality.append(u'%s/%s' % (baseurl, line.replace('\n', '')))
|
|
|
|
if len(links_by_quality):
|
|
try:
|
|
return links_by_quality[self.quality[1]]
|
|
except:
|
|
return links_by_quality[0]
|
|
return NotAvailable
|
|
|
|
def get_video_from_program_id(self, _id):
|
|
class_name = 'epg'
|
|
method_name = 'program'
|
|
parameters = '/'.join([self.lang.get('webservice'), 'L2', _id])
|
|
video = self.webservice.go(class_name=class_name, method_name=method_name,
|
|
parameters=parameters).get_program_video()
|
|
return self.get_video(video.id, video)
|
|
|
|
def latest_videos(self):
|
|
class_name = 'videos'
|
|
method_name = 'plus7'
|
|
parameters = '/'.join([self.lang.get('webservice'), 'L1', 'ALL', 'ALL', '-1', self.order, '10', '0'])
|
|
return self.webservice.go(class_name=class_name, method_name=method_name, parameters=parameters).iter_videos()
|
|
|
|
def get_arte_programs(self):
|
|
class_name = 'epg'
|
|
method_name = 'clusters'
|
|
parameters = '/'.join([self.lang.get('webservice'), '0', 'ALL'])
|
|
return self.webservice.go(class_name=class_name, method_name=method_name,
|
|
parameters=parameters).iter_programs(title=self.lang.get('title'))
|
|
|
|
def get_arte_program_videos(self, program):
|
|
class_name = 'epg'
|
|
method_name = 'cluster'
|
|
parameters = '/'.join([self.lang.get('webservice'), program[-1]])
|
|
available_videos = self.webservice.go(class_name=class_name, method_name=method_name,
|
|
parameters=parameters).iter_program_videos()
|
|
for item in available_videos:
|
|
yield self.get_video_from_program_id(item.id)
|
|
|
|
def get_arte_concert_categories(self):
|
|
return self.videos_list.go(site=SITE.CONCERT.get('id'), lang=self.lang.get('site'),
|
|
cat='').iter_arte_concert_categories()
|
|
|
|
def get_arte_concert_videos(self, cat):
|
|
return self.videos_list.go(site=SITE.CONCERT.get('id'), lang=self.lang.get('site'),
|
|
cat='').iter_arte_concert_videos(cat=cat[-1])
|
|
|
|
def get_arte_concert_video(self, id, video=None):
|
|
json_url = self.video_page.go(_site=SITE.CONCERT.get('id'), id=id).get_json_url()
|
|
m = re.search('http://(?P<__site>.*).arte.tv/(?P<_lang>\w{2})/player/(?P<_id>.*)', json_url)
|
|
if m:
|
|
video = self.webservice.go(__site=m.group('__site'), _lang=m.group('_lang'),
|
|
_id=m.group('_id')).get_arte_concert_video(obj=video)
|
|
video.ext, video.url = self.get_url()
|
|
return video
|
|
|
|
def get_arte_cinema_categories(self, cat=[]):
|
|
menu = self.videos_list.go(site=SITE.CINEMA.get('id'), lang=self.lang.get('site'),
|
|
cat='').get_arte_cinema_menu()
|
|
|
|
menuSplit = map(lambda x: x.split("/")[2:], menu)
|
|
|
|
result = {}
|
|
for record in menuSplit:
|
|
here = result
|
|
for item in record[:-1]:
|
|
if item not in here:
|
|
here[item] = {}
|
|
here = here[item]
|
|
if "end" not in here:
|
|
here["end"] = []
|
|
here["end"].append(record[-1])
|
|
|
|
cat = cat if not cat else cat[1:]
|
|
|
|
for el in cat:
|
|
result = result.get(el)
|
|
|
|
if "end" in result.keys():
|
|
return self.page.iter_arte_cinema_categories(cat='/'.join(cat))
|
|
else:
|
|
categories = []
|
|
for item in result.keys():
|
|
categories.append(Collection([SITE.CINEMA.get('id'), unicode(item)], unicode(item)))
|
|
return categories
|
|
|
|
def get_arte_cinema_videos(self, cat):
|
|
return self.videos_list.go(site=SITE.CINEMA.get('id'), lang=self.lang.get('site'),
|
|
cat='/%s' % '/'.join(cat[1:])).get_arte_cinema_videos()
|
|
|
|
def get_arte_cinema_video(self, id, video=None):
|
|
json_url = self.video_page.go(_site=SITE.CINEMA.get('id'), id=id).get_json_url()
|
|
m = re.search('https://api.arte.tv/api/player/v1/config/(\w{2})/(.*)\?vector=(.*)\&.*', json_url)
|
|
if m:
|
|
video = self.webservice.go(__lang=m.group(1),
|
|
vid=m.group(2), ___site=m.group(3)).get_arte_cinema_video(obj=video)
|
|
video.ext, video.url = self.get_url()
|
|
video.id = id
|
|
return video
|