diff --git a/modules/radiofrance/browser.py b/modules/radiofrance/browser.py index 05f174a0..630a8337 100644 --- a/modules/radiofrance/browser.py +++ b/modules/radiofrance/browser.py @@ -18,13 +18,14 @@ # along with weboob. If not, see . from weboob.browser import PagesBrowser, URL -from .pages import PlayerPage, TimelinePage +from .pages import PlayerPage, JsonPage __all__ = ['RadioFranceBrowser'] class RadioFranceBrowser(PagesBrowser): - timeline = URL('sites/default/files/(?P.*).json', TimelinePage) + json_page = URL('sites/default/files/(?P.*).json', + 'player-json/reecoute/(?P.*)', JsonPage) player_page = URL('(?P.*)', PlayerPage) def get_radio_url(self, radio, player): @@ -33,4 +34,22 @@ class RadioFranceBrowser(PagesBrowser): def get_current(self, radio, json_url): self.BASEURL = 'http://www.%s.fr/' % radio - return self.timeline.go(json_url=json_url).get_current() + return self.json_page.go(json_url=json_url).get_current() + + def get_selection(self, radio_url, json_url, radio_id): + self.BASEURL = 'http://www.%s.fr/' % radio_url + if radio_id == 'fipradio': + return self.json_page.go(json_url_fip=json_url).get_selection(radio_id=radio_id) + + return self.json_page.go(json_url=json_url).get_selection(radio_id=radio_id) + + def get_audio(self, _id, radio_url, json_url, radio_id): + for item in self.get_selection(radio_url, json_url, radio_id): + if item.id == _id: + return item + return [] + + def search_audio(self, pattern, radio_url, json_url, radio_id): + for item in self.get_selection(radio_url, json_url, radio_id): + if pattern.upper() in item.title.upper(): + yield item diff --git a/modules/radiofrance/module.py b/modules/radiofrance/module.py index 673859f1..1a24f806 100644 --- a/modules/radiofrance/module.py +++ b/modules/radiofrance/module.py @@ -20,6 +20,7 @@ from weboob.capabilities.base import NotLoaded from weboob.capabilities.radio import CapRadio, Radio +from weboob.capabilities.audio import CapAudio, BaseAudio from weboob.capabilities.audiostream import BaseAudioStream from weboob.tools.capabilities.streaminfo import StreamInfo from weboob.capabilities.collection import CapCollection, CollectionNotFound, Collection @@ -27,13 +28,14 @@ from weboob.tools.backend import Module from .browser import RadioFranceBrowser +import re import time from datetime import datetime __all__ = ['RadioFranceModule'] -class RadioFranceModule(Module, CapRadio, CapCollection): +class RadioFranceModule(Module, CapRadio, CapCollection, CapAudio): NAME = 'radiofrance' MAINTAINER = u'Laurent Bachelier' EMAIL = 'laurent@bachelier.name' @@ -42,72 +44,240 @@ class RadioFranceModule(Module, CapRadio, CapCollection): LICENSE = 'AGPLv3+' BROWSER = RadioFranceBrowser - _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'), + _RADIOS = { + 'franceinter': {u'title': u'France Inter', + u'player': u'player', + u'live': u'lecteur_commun_json/timeline', + u'selection': u'lecteur_commun_json/reecoute-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'franceculture': {u'title': u'France Culture', + u'player': u'player', + u'live': u'lecteur_commun_json/timeline', + u'selection': u'lecteur_commun_json/reecoute-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'franceinfo': {u'title': u'France Info', + u'player': u'player', + u'live': u'lecteur_commun_json/timeline', + u'selection': u'lecteur_commun_json/reecoute-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbidf': {u'title': u'France Bleu Île-de-France (Paris)', + u'player': u'player/france-bleu-107-1', + u'live': u'lecteur_commun_json/timeline-9753', + u'selection': u'lecteur_commun_json/reecoute-9753-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fipradio': {u'title': u'FIP', + u'player': u'player', + u'live': 'import_si/si_titre_antenne/FIP_player_current', + u'selection': u'%s' % int(time.mktime(datetime.now().replace(hour=12, minute=0, second=0).timetuple()))}, + 'francemusique': {u'title': u'France Musique', + u'player': u'player', + u'live': u'lecteur_commun_json/reecoute-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple())), + u'selection': u'lecteur_commun_json/reecoute-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'mouv': {u'title': u'Le Mouv\'', + u'player': u'player', + u'live': u'lecteur_commun_json/timeline', + u'selection': u'lecteur_commun_json/reecoute-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbalsace': {u'title': u'France Bleu Alsace (Strasbourg)', + u'player': u'player/station/france-bleu-alsace', + u'live': u'lecteur_commun_json/timeline-13085', + u'selection': u'lecteur_commun_json/reecoute-13085-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbarmorique': {u'title': u'France Bleu Armorique (Rennes)', + u'player': u'player/station/france-bleu-armorique', + u'live': u'lecteur_commun_json/timeline-13087', + u'selection': u'lecteur_commun_json/reecoute-13087-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbauxerre': {u'title': u'France Bleu Auxerre', + u'player': u'player/station/france-bleu-auxerre', + u'live': u'lecteur_commun_json/timeline-11219', + u'selection': u'lecteur_commun_json/reecoute-11219-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbazur': {u'title': u'France Bleu Azur (Nice)', + u'player': u'player/station/france-bleu-azur', + u'live': u'lecteur_commun_json/timeline-13089', + u'selection': u'lecteur_commun_json/reecoute-13089-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbbassenormandie': {u'title': u'France Bleu Basse Normandie (Caen)', + u'player': u'player/station/france-bleu-bassenormandie', + u'live': u'lecteur_commun_json/timeline-13091', + u'selection': u'lecteur_commun_json/reecoute-13091-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbbearn': {u'title': u'France Bleu Bearn (Pau)', + u'player': u'player/station/france-bleu-bearn', + u'live': u'lecteur_commun_json/timeline-13093', + u'selection': u'lecteur_commun_json/reecoute-13093-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbbelfort': {u'title': u'France Bleu Belfort', + u'player': u'player/station/france-bleu-belfort', + u'live': u'lecteur_commun_json/timeline-13095', + u'selection': u'lecteur_commun_json/reecoute-13095-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbberry': {u'title': u'France Bleu Berry (Châteauroux)', + u'player': u'player/station/france-bleu-berry', + u'live': u'lecteur_commun_json/timeline-11223', + u'selection': u'lecteur_commun_json/reecoute-11223-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbbesancon': {u'title': u'France Bleu Besancon', + u'player': u'player/station/france-bleu-besancon', + u'live': u'lecteur_commun_json/timeline-13097', + u'selection': u'lecteur_commun_json/reecoute-13097-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbbourgogne': {u'title': u'France Bleu Bourgogne (Dijon)', + u'player': u'player/station/france-bleu-bourgogne', + u'live': u'lecteur_commun_json/timeline-13099', + u'selection': u'lecteur_commun_json/reecoute-13099-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbbreizizel': {u'title': u'France Bleu Breiz Izel (Quimper)', + u'player': u'player/station/france-bleu-breizizel', + u'live': u'lecteur_commun_json/timeline-13101', + u'selection': u'lecteur_commun_json/reecoute-13101-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbchampagne': {u'title': u'France Bleu Champagne (Reims)', + u'player': u'player/station/france-bleu-champagne', + u'live': u'lecteur_commun_json/timeline-13103', + u'selection': u'lecteur_commun_json/reecoute-13103-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbcotentin': {u'title': u'France Bleu Cotentin (Cherbourg)', + u'player': u'player/station/france-bleu-cotentin', + u'live': u'lecteur_commun_json/timeline-13105', + u'selection': u'lecteur_commun_json/reecoute-13105-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbcreuse': {u'title': u'France Bleu Creuse (Gueret)', + u'player': u'player/station/france-bleu-creuse', + u'live': u'lecteur_commun_json/timeline-13107', + u'selection': u'lecteur_commun_json/reecoute-13107-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbdromeardeche': {u'title': u'France Bleu Drome Ardeche (Valence)', + u'player': u'player/station/france-bleu-dromeardeche', + u'live': u'lecteur_commun_json/timeline-13109', + u'selection': u'lecteur_commun_json/reecoute-13109-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbelsass': {u'title': u'France Bleu Elsass', + u'player': 'player/station/france-bleu-elsass', + u'live': u'lecteur_commun_json/timeline-19370', + u'selection': u'lecteur_commun_json/reecoute-19370-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbgardlozere': {u'title': u'France Bleu Gard Lozère (Nîmes)', + u'player': u'player/station/france-bleu-gardlozere', + u'live': u'lecteur_commun_json/timeline-13111', + u'selection': u'lecteur_commun_json/reecoute-13111-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbgascogne': {u'title': u'France Bleu Gascogne (Mont-de-Marsan)', + u'player': u'player/station/france-bleu-gascogne', + u'live': u'lecteur_commun_json/timeline-13113', + u'selection': u'lecteur_commun_json/reecoute-13113-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbgironde': {u'title': u'France Bleu Gironde (Bordeaux)', + u'player': u'player/station/france-bleu-gironde', + u'live': u'lecteur_commun_json/timeline-13115', + u'selection': u'lecteur_commun_json/reecoute-13115-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbhautenormandie': {u'title': u'France Bleu Haute Normandie (Rouen)', + u'player': u'player/station/france-bleu-hautenormandie', + u'live': u'lecteur_commun_json/timeline-13117', + u'selection': u'lecteur_commun_json/reecoute-13117-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbherault': {u'title': u'France Bleu Hérault (Montpellier)', + u'player': u'player/station/france-bleu-herault', + u'live': u'lecteur_commun_json/timeline-11231', + u'selection': u'lecteur_commun_json/reecoute-11231-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbisere': {u'title': u'France Bleu Isère (Grenoble)', + u'player': u'player/station/france-bleu-isere', + u'live': u'lecteur_commun_json/timeline-13119', + u'selection': u'lecteur_commun_json/reecoute-13119-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fblarochelle': {u'title': u'France Bleu La Rochelle', + u'player': u'player/station/france-bleu-larochelle', + u'live': u'lecteur_commun_json/timeline-13121', + u'selection': u'lecteur_commun_json/reecoute-13121-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fblimousin': {u'title': u'France Bleu Limousin (Limoges)', + u'player': u'player/station/france-bleu-limousin', + u'live': u'lecteur_commun_json/timeline-13123', + u'selection': u'lecteur_commun_json/reecoute-13123-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbloireocean': {u'title': u'France Bleu Loire Océan (Nantes)', + u'player': u'player/station/france-bleu-loireocean', + u'live': u'lecteur_commun_json/timeline-13125', + u'selection': u'lecteur_commun_json/reecoute-13125-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fblorrainenord': {u'title': u'France Bleu Lorraine Nord (Metz)', + u'player': u'player/station/france-bleu-lorrainenord', + u'live': u'lecteur_commun_json/timeline-13127', + u'selection': u'lecteur_commun_json/reecoute-13127-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbmaine': {u'title': u'France Bleu Maine', + u'player': 'player/station/france-bleu-maine', + u'live': u'lecteur_commun_json/timeline-13129', + u'selection': u'lecteur_commun_json/reecoute-13129-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbmayenne': {u'title': u'France Bleu Mayenne (Laval)', + u'player': u'player/station/france-bleu-mayenne', + u'live': u'lecteur_commun_json/timeline-13131', + u'selection': u'lecteur_commun_json/reecoute-13131-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbnord': {u'title': u'France Bleu Nord (Lille)', + u'player': u'player/station/france-bleu-nord', + u'live': u'lecteur_commun_json/timeline-11235', + u'selection': u'lecteur_commun_json/reecoute-11235-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fborleans': {u'title': u'France Bleu Orléans', + u'player': u'player/station/france-bleu-orleans', + u'live': u'lecteur_commun_json/timeline-13133', + u'selection': u'lecteur_commun_json/reecoute-13133-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbpaysbasque': {u'title': u'France Bleu Pays Basque (Bayonne)', + u'player': u'player/station/france-bleu-paysbasque', + u'live': u'lecteur_commun_json/timeline-13135', + u'selection': u'lecteur_commun_json/reecoute-13135-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbpaysdauvergne': {u'title': u'France Bleu Pays d\'Auvergne (Clermont-Ferrand)', + u'player': u'player/station/france-bleu-paysdauvergne', + u'live': u'lecteur_commun_json/timeline-11237', + u'selection': u'lecteur_commun_json/reecoute-11237-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbpaysdesavoie': {u'title': u'France Bleu Pays de Savoie (Chambery)', + u'player': u'player/station/france-bleu-paysdesavoie', + u'live': u'lecteur_commun_json/timeline-11239', + u'selection': u'lecteur_commun_json/reecoute-11239-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbperigord': {u'title': u'France Bleu Périgord (Périgueux)', + u'player': u'player/station/france-bleu-perigord', + u'live': u'lecteur_commun_json/timeline-13137', + u'selection': u'lecteur_commun_json/reecoute-13137-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbpicardie': {u'title': u'France Bleu Picardie (Amiens)', + u'player': u'player/station/france-bleu-picardie', + u'live': u'lecteur_commun_json/timeline-13139', + u'selection': u'lecteur_commun_json/reecoute-13139-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbpoitou': {u'title': u'France Bleu Poitou (Poitiers)', + u'player': u'player/station/france-bleu-poitou', + u'live': u'lecteur_commun_json/timeline-13141', + u'selection': u'lecteur_commun_json/reecoute-13141-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbprovence': {u'title': u'France Bleu Provence (Aix-en-Provence)', + u'player': u'player/station/france-bleu-provence', + u'live': u'lecteur_commun_json/timeline-11241', + u'selection': u'lecteur_commun_json/reecoute-11241-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbrcfm': {u'title': u'France Bleu RCFM', + u'player': u'player/station/france-bleu-rcfm', + u'live': u'lecteur_commun_json/timeline-13143', + u'selection': u'lecteur_commun_json/reecoute-13143-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbsaintetienneloire': {u'title': u'France Bleu Saint-Etienne Loire', + u'player': u'player/station/france-bleu-saint-etienne-loire', + u'live': u'lecteur_commun_json/timeline-60434', + u'selection': u'lecteur_commun_json/reecoute-60434-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbroussillon': {u'title': u'France Bleu Roussillon', + u'player': u'player/station/france-bleu-roussillon', + u'live': u'lecteur_commun_json/timeline-11243', + u'selection': u'lecteur_commun_json/reecoute-11243-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbsudlorraine': {u'title': u'France Bleu Sud Lorraine (Nancy)', + u'player': u'player/station/france-bleu-sudlorraine', + u'live': u'lecteur_commun_json/timeline-13145', + u'selection': u'lecteur_commun_json/reecoute-13145-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbtoulouse': {u'title': u'France Bleu Toulouse', + u'player': u'player/station/france-bleu-toulouse', + u'live': u'lecteur_commun_json/timeline-13147', + u'selection': u'lecteur_commun_json/reecoute-13147-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbtouraine': {u'title': u'France Bleu Touraine (Tours)', + u'player': u'player/station/france-bleu-touraine', + u'live': u'lecteur_commun_json/timeline-13149', + u'selection': u'lecteur_commun_json/reecoute-13149-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, + 'fbvaucluse': {u'title': u'France Bleu Vaucluse (Avignon)', + u'player': u'player/station/france-bleu-vaucluse', + u'live': u'lecteur_commun_json/timeline-13151', + u'selection': u'lecteur_commun_json/reecoute-13151-%s' % int(time.mktime(datetime.now().replace(hour=14, minute=0, second=0).timetuple()))}, } def iter_resources(self, objs, split_path): - if Radio in objs: - if split_path == [u'francebleu']: + if split_path and split_path[0] == u'francebleu': + if len(split_path) == 1: for _id, item in sorted(self._RADIOS.iteritems()): if _id.startswith('fb'): - yield Collection([_id], iter(item).next()) - elif len(split_path) == 0: + yield Collection([_id], item['title']) + elif len(split_path) == 2: for _id, item in sorted(self._RADIOS.iteritems()): - if not _id.startswith('fb'): - yield Collection([_id], iter(item).next()) - yield Collection([u'francebleu'], u'France Bleu') - else: - raise CollectionNotFound(split_path) + if _id == split_path[1]: + selection_url = self._RADIOS[_id]['selection'] + for item in self.browser.get_selection('francebleu', selection_url, _id): + yield item + break + elif len(split_path) == 0: + for _id, item in sorted(self._RADIOS.iteritems()): + if not _id.startswith('fb'): + yield Collection([_id], item['title']) + yield Collection([u'francebleu'], u'France Bleu') + elif len(split_path) == 1: + for _id, item in sorted(self._RADIOS.iteritems()): + if _id == split_path[0]: + selection_url = self._RADIOS[_id]['selection'] + for item in self.browser.get_selection(_id, selection_url, _id): + yield item + break + else: + raise CollectionNotFound(split_path) def get_radio(self, radio): @@ -130,7 +300,8 @@ class RadioFranceModule(Module, CapRadio, CapCollection): if radio.id not in self._RADIOS: return None - title, player_url, json_url = self._RADIOS[radio.id] + title = self._RADIOS[radio.id]['title'] + player_url = self._RADIOS[radio.id]['player'] radio.title = title radio.description = title radio_name = radio.id if not radio.id.startswith('fb') else 'francebleu' @@ -142,13 +313,44 @@ class RadioFranceModule(Module, CapRadio, CapCollection): def fill_radio(self, radio, fields): if 'current' in fields: - title, player_url, json_url = self._RADIOS[radio.id] + title = self._RADIOS[radio.id]['title'] + json_url = self._RADIOS[radio.id]['live'] 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 + return radio - OBJECTS = {Radio: fill_radio} + def fill_audio(self, audio, fields): + if 'thumbnail' in fields and audio.thumbnail: + audio.thumbnail.data = self.browser.open(audio.thumbnail.url) + return audio + + def get_radio_id(self, audio_id): + m = re.match('^\w+\.(\w+)\..*', audio_id) + if m: + return m.group(1) + return '' + + def search_audio(self, pattern, sortby=CapAudio.SEARCH_RELEVANCE): + for radio in self._RADIOS: + selection_url = self._RADIOS[radio]['selection'] + radio_url = radio if not radio.startswith('fb') else 'francebleu' + for item in self.browser.search_audio(pattern, radio_url, selection_url, radio): + yield item + + def get_audio(self, _id): + radio = self.get_radio_id(_id) + if radio in self._RADIOS: + selection_url = self._RADIOS[radio]['selection'] + radio_url = radio if not radio.startswith('fb') else 'francebleu' + return self.browser.get_audio(_id, radio_url, selection_url, radio) + + def iter_radios_search(self, pattern): + for key, radio in self._RADIOS.iteritems(): + if pattern.lower() in radio['title'].lower() or pattern.lower() in key.lower(): + yield self.get_radio(key) + + OBJECTS = {Radio: fill_radio, BaseAudio: fill_audio} diff --git a/modules/radiofrance/pages.py b/modules/radiofrance/pages.py index 0ee79607..fe53ee12 100644 --- a/modules/radiofrance/pages.py +++ b/modules/radiofrance/pages.py @@ -17,9 +17,15 @@ # You should have received a copy of the GNU Affero General Public License # along with weboob. If not, see . +from weboob.browser.elements import ItemElement, DictElement, method from weboob.browser.pages import HTMLPage, JsonPage -from weboob.browser.filters.standard import CleanText +from weboob.browser.filters.json import Dict +from weboob.browser.filters.standard import Format, CleanText, Join, Env +from weboob.capabilities.audio import BaseAudio, BaseAudioIdFilter +from weboob.capabilities.image import BaseImage + import time +from datetime import timedelta class PlayerPage(HTMLPage): @@ -27,12 +33,41 @@ class PlayerPage(HTMLPage): return CleanText('//a[@id="player"][1]/@href')(self.doc) -class TimelinePage(JsonPage): +class JsonPage(JsonPage): + @method + class get_selection(DictElement): + item_xpath = 'diffusions' + + class item(ItemElement): + klass = BaseAudio + + obj_id = BaseAudioIdFilter(Format(u'%s.%s', Env('radio_id'), Dict('nid'))) + obj_format = u'mp3' + obj_title = Format(u'%s : %s', + Dict('title_emission'), + Dict('title_diff')) + obj_description = Dict('desc_emission', default=u'') + + obj_author = Join(u', ', Dict('personnes', default=u'')) + obj_url = Dict('path_mp3') + + def obj_thumbnail(self): + if 'path_img_emission' in self.el: + thumbnail = BaseImage(Dict('path_img_emission')(self)) + thumbnail.url = thumbnail.id + return thumbnail + + def obj_duration(self): + fin = Dict('fin')(self) + debut = Dict('debut')(self) + if debut and fin: + return timedelta(seconds=int(fin) - int(debut)) + 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) + title = u'%s: %s' % (emission_title, song_title) person = self.doc['current']['song']['interpreteMorceau'] return person, title elif 'diffusions' in self.doc: @@ -46,8 +81,8 @@ class TimelinePage(JsonPage): else: now = int(time.time()) for item in self.doc: - if item['debut'] < now and item['fin'] > now: - emission = '' + if int(item['debut']) < now and int(item['fin']) > now: + emission = u'' if 'diffusions' in item and item['diffusions'] and 'title' in item['diffusions'][0]: emission = item['diffusions'][0]['title'] @@ -56,7 +91,7 @@ class TimelinePage(JsonPage): title = u'%s: %s' % (title, emission) person = u'' - if 'personnes' in item: + if 'personnes' in item and item['personnes'] and item['personnes'][0]: person = u','.join(item['personnes']) return person, title return u'', u'' diff --git a/modules/radiofrance/test.py b/modules/radiofrance/test.py index 3c2e1cf9..713de45a 100644 --- a/modules/radiofrance/test.py +++ b/modules/radiofrance/test.py @@ -19,15 +19,16 @@ from weboob.tools.test import BackendTest -from weboob.capabilities.video import BaseVideo +from weboob.capabilities.audio import BaseAudio from weboob.capabilities.radio import Radio class RadioFranceTest(BackendTest): MODULE = 'radiofrance' - def test_get_radios(self): + def test_get_radios_and_selections(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] @@ -35,6 +36,10 @@ class RadioFranceTest(BackendTest): streams = self.backend.get_radio(name).streams self.assertTrue(len(streams) > 0) + l_sel = list(self.backend.iter_resources(objs=[BaseAudio], split_path=[name])) + self.assertTrue(len(l_sel) > 0) + self.assertTrue(len(l_sel[0].url) > 0) + l = list(self.backend.iter_resources(objs=[Radio], split_path=['francebleu'])) self.assertTrue(len(l) > 30) @@ -42,5 +47,18 @@ class RadioFranceTest(BackendTest): 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) + l_sel = list(self.backend.iter_resources(objs=[BaseAudio], split_path=['francebleu', radio.split_path[-1]])) + if len(l_sel) > 0: + self.assertTrue(len(l_sel[0].url) > 0) + + def test_search_radio(self): + l = list(self.backend.iter_radios_search('bleu')) + self.assertTrue(len(l) > 0) + self.assertTrue(len(l[0].streams) > 0) + + def test_search_get_audio(self): + l = list(self.backend.search_audio('journal')) + self.assertTrue(len(l) > 0) + + a = self.backend.get_audio(l[0].id) + self.assertTrue(a.url)