From cfb603c6ad54aa06f6dcc21e577fa846531f4c7f Mon Sep 17 00:00:00 2001 From: Bezleputh Date: Thu, 25 Jun 2015 13:57:25 +0200 Subject: [PATCH] [radiofrance] site changed / backend rewritten using browser2 --- modules/radiofrance/browser.py | 176 ++------------------------ modules/radiofrance/module.py | 222 +++++++++++++-------------------- modules/radiofrance/pages.py | 62 +++++++++ modules/radiofrance/test.py | 39 ++---- 4 files changed, 170 insertions(+), 329 deletions(-) create mode 100644 modules/radiofrance/pages.py diff --git a/modules/radiofrance/browser.py b/modules/radiofrance/browser.py index 32ccc8c8..05f174a0 100644 --- a/modules/radiofrance/browser.py +++ b/modules/radiofrance/browser.py @@ -17,172 +17,20 @@ # You should have received a copy of the GNU Affero General Public License # along with weboob. If not, see . -from weboob.deprecated.browser import Browser, Page -from weboob.tools.json import json -from weboob.capabilities.video import BaseVideo -from weboob.deprecated.browser.decorators import id2url +from weboob.browser import PagesBrowser, URL +from .pages import PlayerPage, TimelinePage -from time import time -import re -from urlparse import parse_qs +__all__ = ['RadioFranceBrowser'] -__all__ = ['RadioFranceBrowser', 'RadioFranceVideo'] +class RadioFranceBrowser(PagesBrowser): + timeline = URL('sites/default/files/(?P.*).json', TimelinePage) + player_page = URL('(?P.*)', PlayerPage) + def get_radio_url(self, radio, player): + self.BASEURL = 'http://www.%s.fr/' % radio + return self.player_page.go(player=player).get_url() -class RadioFranceVideo(BaseVideo): - RADIO_DOMAINS = ('franceinter', 'franceculture', 'fipradio', 'franceinfo') - - def __init__(self, *args, **kwargs): - BaseVideo.__init__(self, *args, **kwargs) - self.ext = u'mp3' - - @classmethod - def id2url(cls, _id): - radio_id, replay_id = _id.split('-', 2) - radio_domain = 'fipradio' if radio_id == 'fip' else radio_id - return 'http://www.%s.fr/player/reecouter?play=%s' % \ - (radio_domain, replay_id) - - -class PlayerPage(Page): - URL = r'^http://www\.(?P%s)\.fr/player/reecouter\?play=(?P\d+)$' \ - % '|'.join(RadioFranceVideo.RADIO_DOMAINS) - MP3_REGEXP = re.compile(r'sites%2Fdefault.+.(?:MP3|mp3)') - - def get_url(self): - radio_domain = self.groups[0] - player = self.parser.select(self.document.getroot(), '#rfPlayer embed', 1) - urlparams = parse_qs(player.attrib['src']) - return 'http://www.%s.fr/%s' % (radio_domain, urlparams['urlAOD'][0]) - - -class ReplayPage(Page): - URL = r'^http://www\.(?P%s)\.fr/(?:emission|diffusion)-.+$' \ - % '|'.join(RadioFranceVideo.RADIO_DOMAINS) - # the url does not always end with id-yyy-mm-dd, sometimes no mm or dd - URL2 = r'^http://www\.(?P%s)\.fr/[a-z\-]+/[0-9a-z\-]+/[0-9a-z\-]+-[0-9\-]+' \ - % 'franceinfo' - - def get_id(self): - radio_domain = self.groups[0] - for node in self.parser.select(self.document.getroot(), 'div.node-rf_diffusion'): - match = re.match(r'^node-(\d+)$', node.attrib.get('id', '')) - if match: - player_id = match.groups()[0] - return (radio_domain, player_id) - # if we failed, try another way (used in FIP) - # but it might not be as accurate for others - # (some pages have more than one of these) - # so it's only used as a fallback - for node in self.parser.select(self.document.getroot(), 'a.rf-player-open'): - match = re.match(r'^/player/reecouter\?play=(\d+)$', node.attrib.get('href', '')) - if match: - player_id = match.groups()[0] - return (radio_domain, player_id) - # at least for franceinfo - for node in self.parser.select(self.document.getroot(), '#article .emission-player a.play'): - match = re.match(r'^song-(\d+)$', node.attrib.get('rel', '')) - if match: - player_id = match.groups()[0] - return (radio_domain, player_id) - - -class DataPage(Page): - def get_current(self): - document = self.document - title = '' - for metas in self.parser.select(document.getroot(), 'div.metas'): - ftitle = unicode(metas.text_content()).strip() - if ftitle: - title = ftitle - # Another format (used by FIP) - artist = document.findtext('//div[@class="metas"]//span[@class="author"]') - if artist: - artist = unicode(artist).strip() - ftitle = document.findtext('//div[@class="subtitle"]') - title = unicode(ftitle).strip() if ftitle else title - else: - artist = '' - - return (artist, title) - - -class RssPage(Page): - def get_title(self): - titles = [] - for heading in self.parser.select(self.document.getroot(), 'h1, h2, h3, h4'): - # Remove newlines/multiple spaces - words = heading.text_content() - if words: - for word in unicode(words).split(): - titles.append(word) - if len(titles): - return ' '.join(titles) - - -class RadioFranceBrowser(Browser): - DOMAIN = None - ENCODING = 'UTF-8' - PAGES = {r'http://.*/player/direct': DataPage, - r'http://players.tv-radio.com/radiofrance/metadatas/([a-z]+)RSS.html': RssPage, - PlayerPage.URL: PlayerPage, - ReplayPage.URL: ReplayPage, - ReplayPage.URL2: ReplayPage} - - def id2domain(self, _id): - """ - Get the main website domain for a Radio ID. - """ - # FIP is the only one to use "fip" but "fipradio" for the domain. - if _id == 'fip': - _id = 'fipradio' - return 'www.%s.fr' % _id - - def get_current_playerjs(self, _id): - self.location('http://%s/player/direct' % self.id2domain(_id)) - assert self.is_on_page(DataPage) - - return self.page.get_current() - - def get_current_rss(self, _id): - self.location('http://players.tv-radio.com/radiofrance/metadatas/%sRSS.html' % _id) - assert self.is_on_page(RssPage) - - return self.page.get_title() - - def get_current_direct(self, _id): - json_data = self.openurl('http://%s/sites/default/files/direct.json?_=%s' % (self.id2domain(_id), int(time()))) - data = json.load(json_data) - title = unicode(data['rf_titre_antenne']['titre']) - artist = unicode(data['rf_titre_antenne']['interprete']) - return (artist, title) - - def get_current_direct_large(self, _id): - json_data = self.openurl('http://%s/sites/default/files/import_si/si_titre_antenne/FIP_player_current.json' - % self.id2domain(_id)) - data = json.load(json_data) - artist = unicode(data['current']['song']['interpreteMorceau']) - title = unicode(data['current']['song']['titre']) - return (artist, title) - - @id2url(RadioFranceVideo.id2url) - def get_video(self, url): - radio_domain = replay_id = None - match = re.match(PlayerPage.URL, url) - if match: - radio_domain, replay_id = match.groups() - elif re.match(ReplayPage.URL, url) or re.match(ReplayPage.URL2, url): - self.location(url) - assert self.is_on_page(ReplayPage) - radio_domain, replay_id = self.page.get_id() - if radio_domain and replay_id: - radio_id = 'fip' if radio_domain == 'fipradio' else radio_domain - _id = '%s-%s' % (radio_id, replay_id) - return RadioFranceVideo(_id) - - @id2url(RadioFranceVideo.id2url) - def get_url(self, url): - self.location(url) - assert self.is_on_page(PlayerPage) - return self.page.get_url() + def get_current(self, radio, json_url): + self.BASEURL = 'http://www.%s.fr/' % radio + return self.timeline.go(json_url=json_url).get_current() diff --git a/modules/radiofrance/module.py b/modules/radiofrance/module.py index 3bf271ab..673859f1 100644 --- a/modules/radiofrance/module.py +++ b/modules/radiofrance/module.py @@ -19,20 +19,21 @@ from weboob.capabilities.base import NotLoaded -from weboob.capabilities.video import CapVideo from weboob.capabilities.radio import CapRadio, Radio from weboob.capabilities.audiostream import BaseAudioStream from weboob.tools.capabilities.streaminfo import StreamInfo from weboob.capabilities.collection import CapCollection, CollectionNotFound, Collection from weboob.tools.backend import Module -from .browser import RadioFranceBrowser, RadioFranceVideo +from .browser import RadioFranceBrowser +import time +from datetime import datetime __all__ = ['RadioFranceModule'] -class RadioFranceModule(Module, CapRadio, CapCollection, CapVideo): +class RadioFranceModule(Module, CapRadio, CapCollection): NAME = 'radiofrance' MAINTAINER = u'Laurent Bachelier' EMAIL = 'laurent@bachelier.name' @@ -41,166 +42,113 @@ class RadioFranceModule(Module, CapRadio, CapCollection, CapVideo): LICENSE = 'AGPLv3+' BROWSER = RadioFranceBrowser - _MP3_URL = u'http://mp3.live.tv-radio.com/%s/all/%s.mp3' - _MP3_HD_URL = u'http://mp3.live.tv-radio.com/%s/all/%shautdebit.mp3' - _RADIOS = {'franceinter': (u'France Inter', True), - 'franceculture': (u'France Culture', True), - 'franceinfo': (u'France Info', False), - 'fbidf': (u'France Bleu Île-de-France (Paris)', True), - 'fip': (u'FIP', True), - 'francemusique': (u'France Musique', True), - 'lemouv': (u'Le Mouv\'', True), - 'fbalsace': (u'France Bleu Alsace (Strasbourg)', False), - 'fbarmorique': (u'France Bleu Armorique (Rennes)', False), - 'fbauxerre': (u'France Bleu Auxerre', False), - 'fbazur': (u'France Bleu Azur (Nice)', False), - 'fbbassenormandie': (u'France Bleu Basse Normandie (Caen)', False), - 'fbbearn': (u'France Bleu Bearn (Pau)', False), - 'fbbelfort': (u'France Bleu Belfort', False), - 'fbberry': (u'France Bleu Berry (Châteauroux)', False), - 'fbbesancon': (u'France Bleu Besancon', False), - 'fbbourgogne': (u'France Bleu Bourgogne (Dijon)', False), - 'fbbreizizel': (u'France Bleu Breiz Izel (Quimper)', False), - 'fbchampagne': (u'France Bleu Champagne (Reims)', False), - 'fbcotentin': (u'France Bleu Cotentin (Cherbourg)', False), - 'fbcreuse': (u'France Bleu Creuse (Gueret)', False), - 'fbdromeardeche': (u'France Bleu Drome Ardeche (Valence)', False), - 'fbfrequenzamora': (u'France Bleu Frequenza Mora (Bastia - Corse)', False), - 'fbgardlozere': (u'France Bleu Gard Lozère (Nîmes)', False), - 'fbgascogne': (u'France Bleu Gascogne (Mont-de-Marsan)', False), - 'fbgironde': (u'France Bleu Gironde (Bordeaux)', False), - 'fbhautenormandie': (u'France Bleu Haute Normandie (Rouen)', False), - 'fbherault': (u'France Bleu Hérault (Montpellier)', False), - 'fbisere': (u'France Bleu Isère (Grenoble)', False), - 'fblarochelle': (u'France Bleu La Rochelle', False), - 'fblimousin': (u'France Bleu Limousin (Limoges)', False), - 'fbloireocean': (u'France Bleu Loire Océan (Nantes)', False), - 'fblorrainenord': (u'France Bleu Lorraine Nord (Metz)', False), - 'fbmayenne': (u'France Bleu Mayenne (Laval)', False), - 'fbnord': (u'France Bleu Nord (Lille)', False), - 'fborleans': (u'France Bleu Orléans', False), - 'fbpaysbasque': (u'France Bleu Pays Basque (Bayonne)', False), - 'fbpaysdauvergne': (u'France Bleu Pays d\'Auvergne (Clermont-Ferrand)', False), - 'fbpaysdesavoie': (u'France Bleu Pays de Savoie (Chambery)', False), - 'fbperigord': (u'France Bleu Périgord (Périgueux)', False), - 'fbpicardie': (u'France Bleu Picardie (Amiens)', False), - 'fbpoitou': (u'France Bleu Poitou (Poitiers)', False), - 'fbprovence': (u'France Bleu Provence (Aix-en-Provence)', False), - 'fbroussillon': (u'France Bleu Roussillon (Perpigan)', False), - 'fbsudlorraine': (u'France Bleu Sud Lorraine (Nancy)', False), - 'fbtoulouse': (u'France Bleu Toulouse', False), - 'fbtouraine': (u'France Bleu Touraine (Tours)', False), - 'fbvaucluse': (u'France Bleu Vaucluse (Avignon)', False), + _RADIOS = {'franceinter': (u'France Inter', 'player', 'lecteur_commun_json/timeline'), + 'franceculture': (u'France Culture', 'player', 'lecteur_commun_json/timeline'), + 'franceinfo': (u'France Info', 'player', 'lecteur_commun_json/timeline'), + 'fbidf': (u'France Bleu Île-de-France (Paris)', 'station/france-bleu-107-1', 'lecteur_commun_json/timeline-9753'), + 'fipradio': (u'FIP', 'player', 'import_si/si_titre_antenne/FIP_player_current'), + 'francemusique': (u'France Musique', 'player', 'lecteur_commun_json/reecoute-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))), + 'mouv': (u'Le Mouv\'', 'player', 'lecteur_commun_json/timeline'), + 'fbalsace': (u'France Bleu Alsace (Strasbourg)', 'player/station/france-bleu-alsace', 'lecteur_commun_json/timeline-13085'), + 'fbarmorique': (u'France Bleu Armorique (Rennes)', 'player/station/france-bleu-armorique', 'lecteur_commun_json/timeline-13087'), + 'fbauxerre': (u'France Bleu Auxerre', 'player/station/france-bleu-auxerre', 'lecteur_commun_json/timeline-11219'), + 'fbazur': (u'France Bleu Azur (Nice)', 'player/station/france-bleu-azur', 'lecteur_commun_json/timeline-13089'), + 'fbbassenormandie': (u'France Bleu Basse Normandie (Caen)', 'player/station/france-bleu-bassenormandie', 'lecteur_commun_json/timeline-13091'), + 'fbbearn': (u'France Bleu Bearn (Pau)', 'player/station/france-bleu-bearn', 'lecteur_commun_json/timeline-13093'), + 'fbbelfort': (u'France Bleu Belfort', 'player/station/france-bleu-belfort', 'lecteur_commun_json/timeline-13095'), + 'fbberry': (u'France Bleu Berry (Châteauroux)', 'player/station/france-bleu-berry', 'lecteur_commun_json/timeline-11223'), + 'fbbesancon': (u'France Bleu Besancon', 'player/station/france-bleu-besancon', 'lecteur_commun_json/timeline-13097'), + 'fbbourgogne': (u'France Bleu Bourgogne (Dijon)', 'player/station/france-bleu-bourgogne', 'lecteur_commun_json/timeline-13099'), + 'fbbreizizel': (u'France Bleu Breiz Izel (Quimper)', 'player/station/france-bleu-breizizel', 'lecteur_commun_json/timeline-13101'), + 'fbchampagne': (u'France Bleu Champagne (Reims)', 'player/station/france-bleu-champagne', 'lecteur_commun_json/timeline-13103'), + 'fbcotentin': (u'France Bleu Cotentin (Cherbourg)', 'player/station/france-bleu-cotentin', 'lecteur_commun_json/timeline-13105'), + 'fbcreuse': (u'France Bleu Creuse (Gueret)', 'player/station/france-bleu-creuse', 'lecteur_commun_json/timeline-13107'), + 'fbdromeardeche': (u'France Bleu Drome Ardeche (Valence)', 'player/station/france-bleu-dromeardeche', 'lecteur_commun_json/timeline-13109'), + 'fbelsass': (u'France Bleu Elsass', '/player/station/france-bleu-elsass', 'lecteur_commun_json/timeline-19370'), + 'fbgardlozere': (u'France Bleu Gard Lozère (Nîmes)', 'player/station/france-bleu-gardlozere', 'lecteur_commun_json/timeline-13111'), + 'fbgascogne': (u'France Bleu Gascogne (Mont-de-Marsan)', 'player/station/france-bleu-gascogne', 'lecteur_commun_json/timeline-13113'), + 'fbgironde': (u'France Bleu Gironde (Bordeaux)', 'player/station/france-bleu-gironde', 'lecteur_commun_json/timeline-13115'), + 'fbhautenormandie': (u'France Bleu Haute Normandie (Rouen)', 'player/station/france-bleu-hautenormandie', 'lecteur_commun_json/timeline-13117'), + 'fbherault': (u'France Bleu Hérault (Montpellier)', 'player/station/france-bleu-herault', 'lecteur_commun_json/timeline-11231'), + 'fbisere': (u'France Bleu Isère (Grenoble)', 'player/station/france-bleu-isere', 'lecteur_commun_json/timeline-13119'), + 'fblarochelle': (u'France Bleu La Rochelle', 'player/station/france-bleu-larochelle', 'lecteur_commun_json/timeline-13121'), + 'fblimousin': (u'France Bleu Limousin (Limoges)', 'player/station/france-bleu-limousin', 'lecteur_commun_json/timeline-13123'), + 'fbloireocean': (u'France Bleu Loire Océan (Nantes)', 'player/station/france-bleu-loireocean', 'lecteur_commun_json/timeline-13125'), + 'fblorrainenord': (u'France Bleu Lorraine Nord (Metz)', 'player/station/france-bleu-lorrainenord', 'lecteur_commun_json/timeline-13127'), + 'fbmaine': (u'France Bleu Maine', '/player/station/france-bleu-maine', 'lecteur_commun_json/timeline-13129'), + 'fbmayenne': (u'France Bleu Mayenne (Laval)', 'player/station/france-bleu-mayenne', 'lecteur_commun_json/timeline-13131'), + 'fbnord': (u'France Bleu Nord (Lille)', 'player/station/france-bleu-nord', 'lecteur_commun_json/timeline-11235'), + 'fborleans': (u'France Bleu Orléans', 'player/station/france-bleu-orleans', 'lecteur_commun_json/timeline-13133'), + 'fbpaysbasque': (u'France Bleu Pays Basque (Bayonne)', 'player/station/france-bleu-paysbasque', 'lecteur_commun_json/timeline-13135'), + 'fbpaysdauvergne': (u'France Bleu Pays d\'Auvergne (Clermont-Ferrand)', 'player/station/france-bleu-paysdauvergne', 'lecteur_commun_json/timeline-11237'), + 'fbpaysdesavoie': (u'France Bleu Pays de Savoie (Chambery)', 'player/station/france-bleu-paysdesavoie', 'lecteur_commun_json/timeline-11239'), + 'fbperigord': (u'France Bleu Périgord (Périgueux)', 'player/station/france-bleu-perigord', 'lecteur_commun_json/timeline-13137'), + 'fbpicardie': (u'France Bleu Picardie (Amiens)', 'player/station/france-bleu-picardie', 'lecteur_commun_json/timeline-13139'), + 'fbpoitou': (u'France Bleu Poitou (Poitiers)', 'player/station/france-bleu-poitou', 'lecteur_commun_json/timeline-13141'), + 'fbprovence': (u'France Bleu Provence (Aix-en-Provence)', 'player/station/france-bleu-provence', 'lecteur_commun_json/timeline-11241'), + 'fbrcfm': (u'France Bleu RCFM', 'player/station/france-bleu-rcfm', 'lecteur_commun_json/timeline-13143'), + 'fbsaintetienneloire': (u'France Bleu Saint-Etienne Loire', 'player/station/france-bleu-saint-etienne-loire', 'lecteur_commun_json/timeline-60434'), + 'fbroussillon': (u'France Bleu Roussillon', 'player/station/france-bleu-roussillon', 'lecteur_commun_json/timeline-11243'), + 'fbsudlorraine': (u'France Bleu Sud Lorraine (Nancy)', 'player/station/france-bleu-sudlorraine', 'lecteur_commun_json/timeline-13145'), + 'fbtoulouse': (u'France Bleu Toulouse', 'player/station/france-bleu-toulouse', 'lecteur_commun_json/timeline-13147'), + 'fbtouraine': (u'France Bleu Touraine (Tours)', 'player/station/france-bleu-touraine', 'lecteur_commun_json/timeline-13149'), + 'fbvaucluse': (u'France Bleu Vaucluse (Avignon)', 'player/station/france-bleu-vaucluse', 'lecteur_commun_json/timeline-13151'), } - _PLAYERJS_RADIOS = ('franceinter', - 'franceculture', - 'franceinfo', - 'lemouv', - ) - - _DIRECTJSON_RADIOS = ('lemouv', ) - _LARGEDIRECTJSON_RADIOS = ('fip', ) - _RSS_RADIOS = ('francemusique', ) - def iter_resources(self, objs, split_path): if Radio in objs: if split_path == [u'francebleu']: - for _id in sorted(self._RADIOS.iterkeys()): + for _id, item in sorted(self._RADIOS.iteritems()): if _id.startswith('fb'): - yield self.get_radio(_id) + yield Collection([_id], iter(item).next()) elif len(split_path) == 0: - for _id in sorted(self._RADIOS.iterkeys()): + for _id, item in sorted(self._RADIOS.iteritems()): if not _id.startswith('fb'): - yield self.get_radio(_id) + yield Collection([_id], iter(item).next()) yield Collection([u'francebleu'], u'France Bleu') else: raise CollectionNotFound(split_path) - def iter_radios_search(self, pattern): - for radio in self.iter_resources_flat((Radio, ), []): - if pattern.lower() in radio.title.lower() or pattern.lower() in radio.description.lower(): - yield radio - def get_radio(self, radio): + + def create_stream(url, hd=True): + stream = BaseAudioStream(0) + if hd: + stream.bitrate = 128 + else: + stream.bitrate = 32 + url = url.replace('midfi128', 'lofi32') + + stream.format = u'mp3' + stream.title = u'%s kbits/s' % (stream.bitrate) + stream.url = url + return stream + if not isinstance(radio, Radio): radio = Radio(radio) if radio.id not in self._RADIOS: return None - title, hd = self._RADIOS[radio.id] + title, player_url, json_url = self._RADIOS[radio.id] radio.title = title radio.description = title + radio_name = radio.id if not radio.id.startswith('fb') else 'francebleu' + url = self.browser.get_radio_url(radio_name, player_url) - if hd: - url = self._MP3_HD_URL % (radio.id, radio.id) - else: - url = self._MP3_URL % (radio.id, radio.id) - - # This should be asked demand, but is required for now as Radioob - # does not require it. self.fillobj(radio, ('current', )) - - stream = BaseAudioStream(0) - if hd: - stream.bitrate = 128 - else: - stream.bitrate = 32 - stream.format = u'mp3' - stream.title = u'%s kbits/s' % (stream.bitrate) - stream.url = url - radio.streams = [stream] + radio.streams = [create_stream(url), create_stream(url, False)] return radio def fill_radio(self, radio, fields): if 'current' in fields: - artist = title = None - if radio.id in self._PLAYERJS_RADIOS: - artist, title = self.browser.get_current_playerjs(radio.id) - if title.endswith(u'par %s' % artist): - artist = None - if radio.id in self._DIRECTJSON_RADIOS: - dartist, dtitle = self.browser.get_current_direct(radio.id) - if dartist: - artist = dartist - if dtitle: - if title: - title = u"%s [%s]" % (dtitle, title) - else: - title = dtitle - elif radio.id in self._LARGEDIRECTJSON_RADIOS: - dartist, dtitle = self.browser.get_current_direct_large(radio.id) - if dartist: - artist = dartist - if dtitle: - title = dtitle - if radio.id in self._RSS_RADIOS: - title = self.browser.get_current_rss(radio.id) - if title: - if not radio.current or radio.current is NotLoaded: - radio.current = StreamInfo(0) - radio.current.what = title - radio.current.who = artist + title, player_url, json_url = self._RADIOS[radio.id] + radio_name = radio.id if not radio.id.startswith('fb') else 'francebleu' + artist, title = self.browser.get_current(radio_name, json_url) + if not radio.current or radio.current is NotLoaded: + radio.current = StreamInfo(0) + radio.current.what = title + radio.current.who = artist return radio - # TODO - # http://www.franceculture.fr/recherche/key%3DYOURSEARCH%2526type%3Demission - # http://www.franceinter.fr/recherche/key%3DYOURSEARCH%2526tri%3Dpertinence%2526theme%3Ddefault%2526type%3Demission - #def search_videos(self, *args, **kwargs): - # return [] - - def get_video(self, _id): - with self.browser: - video = self.browser.get_video(_id) - return video - - def fill_video(self, video, fields): - if 'url' in fields: - with self.browser: - video.url = unicode(self.browser.get_url(video.id)) - - return video - - OBJECTS = {Radio: fill_radio, - RadioFranceVideo: fill_video} + OBJECTS = {Radio: fill_radio} diff --git a/modules/radiofrance/pages.py b/modules/radiofrance/pages.py new file mode 100644 index 00000000..de02d79e --- /dev/null +++ b/modules/radiofrance/pages.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Bezleputh +# +# 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 . + +from weboob.browser.pages import HTMLPage, JsonPage +from weboob.browser.filters.standard import CleanText +import time + + +class PlayerPage(HTMLPage): + def get_url(self): + return CleanText('//a[@id="player"][1]/@href')(self.doc) + + +class TimelinePage(JsonPage): + def get_current(self): + if 'current' in self.doc: + emission_title = self.doc['current']['emission']['titre'] + song_title = self.doc['current']['song']['titre'] + title = '%s: %s' % (emission_title, song_title) + person = self.doc['current']['song']['interpreteMorceau'] + return person, title + elif 'diffusions' in self.doc: + now = int(time.time()) + for item in self.doc['diffusions']: + if item['debut'] < now and item['fin'] > now: + title = u'%s: %s' % (item['title_emission'], item['title_diff']) + person = u'' + return person, title + return u'', u'' + else: + now = int(time.time()) + for item in self.doc: + if item['debut'] < now and item['fin'] > now: + emission = '' + if 'diffusions' in item and item['diffusions']: + emission = item['diffusions'][0]['title'] + + title = item['title_emission'] + if emission: + title = u'%s: %s' % (title, emission) + + person = u'' + if 'personnes' in item: + person = u','.join(item['personnes']) + return person, title + return u'', u'' diff --git a/modules/radiofrance/test.py b/modules/radiofrance/test.py index 8cfdfa59..3c2e1cf9 100644 --- a/modules/radiofrance/test.py +++ b/modules/radiofrance/test.py @@ -29,35 +29,18 @@ class RadioFranceTest(BackendTest): def test_get_radios(self): l = list(self.backend.iter_resources(objs=[Radio], split_path=[])) self.assertTrue(0 < len(l) < 30) + for radio in l: + name = radio.split_path[-1] + if name != 'francebleu': + streams = self.backend.get_radio(name).streams + self.assertTrue(len(streams) > 0) + l = list(self.backend.iter_resources(objs=[Radio], split_path=['francebleu'])) self.assertTrue(len(l) > 30) + + for radio in l: + streams = self.backend.get_radio(radio.split_path[-1]).streams + self.assertTrue(len(streams) > 0) + l = list(self.backend.iter_resources(objs=[BaseVideo], split_path=[])) self.assertEquals(len(l), 0) - - def test_get_video(self): - # this should be available up to 24/10/2014 15h00 - urls = ('http://www.franceinter.fr/emission-vivre-avec-les-betes-y-arthus-bertrand-felins-g-tsai-s-envoler-conte-boreal-reha-hutin-30-m', - 'http://www.franceinter.fr/player/reecouter?play=263735', - 'franceinter-263735') - for url in urls: - vid = self.backend.get_video(url) - assert vid.id == urls[-1] - self.backend.fillobj(vid, ['url']) - assert vid.url.lower().endswith('.mp3') - - # france culture (no expiration known) - vid = self.backend.get_video('http://www.franceculture.fr/emission-la-dispute-expositions-paul-strand-youssef-nabil-et-dorothee-smith-2012-02-01') - assert vid.id - self.backend.fillobj(vid, ['url']) - assert vid.url.lower().endswith('.mp3') - - # fip (no expiration known) - # getting the proper ID is hard, hence the tests with many urls for the same content - urls = ('http://www.fipradio.fr/diffusion-club-jazzafip-du-13-mars', - 'http://www.fipradio.fr/player/reecouter?play=20686', - 'fip-20686') - for url in urls: - vid = self.backend.get_video(url) - assert vid.id == urls[-1] - self.backend.fillobj(vid, ['url']) - assert vid.url.lower().endswith('.mp3')