diff --git a/modules/allocine/browser.py b/modules/allocine/browser.py index 748b2d49..d1b81039 100644 --- a/modules/allocine/browser.py +++ b/modules/allocine/browser.py @@ -17,6 +17,7 @@ # You should have received a copy of the GNU Affero General Public License # along with weboob. If not, see . +from weboob.capabilities.calendar import BaseCalendarEvent, TRANSP, STATUS, CATEGORIES from weboob.capabilities.collection import Collection from weboob.capabilities.video import BaseVideo from weboob.capabilities.image import BaseImage @@ -30,7 +31,6 @@ from datetime import datetime, date, timedelta import time import urllib - __all__ = ['AllocineBrowser'] @@ -492,8 +492,9 @@ class AllocineBrowser(Browser): video.title = unicode(movie['trailer']['name']) video._video_code = unicode(movie['trailer']['code']) video.ext = u'mp4' - video.thumbnail = BaseImage(movie['poster']['href']) - video.thumbnail.url = unicode(movie['poster']['href']) + if 'poster' in movie: + video.thumbnail = BaseImage(movie['poster']['href']) + video.thumbnail.url = unicode(movie['poster']['href']) tdate = movie['release']['releaseDate'].split('-') day = 1 month = 1 @@ -507,7 +508,7 @@ class AllocineBrowser(Browser): if 'userRating' in movie['statistics']: video.rating = movie['statistics']['userRating'] elif 'pressRating' in movie['statistics']: - video.rating = movie['statistics']['pressRating']*2 + video.rating = movie['statistics']['pressRating'] * 2 video.rating_max = 5 if 'synopsis' in movie: video.description = unicode(movie['synopsis'].replace('

', '').replace('

', '')) @@ -561,3 +562,86 @@ class AllocineBrowser(Browser): result = json.loads(res) for emission in result['feed']['term']: yield Collection([basename, unicode(emission['nameShort'])], unicode(emission['$'])) + + def search_events(self, query): + params = [('partner', self.PARTNER_KEY), + ('format', 'json'), + ('zip', query.city) + ] + + if query.summary: + movie = self.iter_movies(query.summary).next() + params.append(('movie', movie.id)) + + res = self.__do_request('showtimelist', params) + if res is None: + return + result = json.loads(res) + + for event in self.create_event(result): + if (not query.end_date or event.start_date <= query.end_date)\ + and event.start_date >= query.start_date: + yield event + + def get_event(self, _id): + split_id = _id.split('#') + params = [('partner', self.PARTNER_KEY), + ('format', 'json'), + ('theaters', split_id[0]), + ('zip', split_id[1]), + ('movie', split_id[2]), + ] + + res = self.__do_request('showtimelist', params) + if res is None: + return + result = json.loads(res) + + for event in self.create_event(result): + if event.id.split('#')[-1] == split_id[-1]: + event.description = self.get_movie(split_id[2]).pitch + return event + + def create_event(self, data): + sequence = 1 + transp = TRANSP.TRANSPARENT + status = STATUS.CONFIRMED + category = CATEGORIES.CINE + + if 'theaterShowtimes' not in data['feed']: + return + + for items in data['feed']['theaterShowtimes']: + cinema = items['place']['theater'] + city = unicode(cinema['city']) + location = u'%s, %s' % (cinema['name'], cinema['address']) + postalCode = cinema['postalCode'] + cinemaCode = cinema['code'] + for show in items['movieShowtimes']: + summary = unicode(show['onShow']['movie']['title']) + movieCode = show['onShow']['movie']['code'] + for jour in show['scr']: + tdate = jour['d'].split('-') + year = int(tdate[0]) + month = int(tdate[1]) + day = int(tdate[2]) + for seance in jour['t']: + ttime = seance['$'].split(':') + heure = int(ttime[0]) + minute = int(ttime[1]) + start_date = datetime(year=year, month=month, day=day, + hour=heure, minute=minute) + + seanceCode = seance['code'] + _id = u'%s#%s#%s#%s' % (cinemaCode, postalCode, movieCode, seanceCode) + event = BaseCalendarEvent() + event.id = _id + event.sequence = sequence + event.transp = transp + event.status = status + event.category = category + event.city = city + event.location = location + event.start_date = start_date + event.summary = summary + yield event diff --git a/modules/allocine/module.py b/modules/allocine/module.py index aec9cd16..a5122631 100644 --- a/modules/allocine/module.py +++ b/modules/allocine/module.py @@ -16,7 +16,10 @@ # # You should have received a copy of the GNU Affero General Public License # along with weboob. If not, see . +import re +from weboob.capabilities.base import UserError +from weboob.capabilities.calendar import CapCalendarEvent, CATEGORIES, BaseCalendarEvent from weboob.capabilities.video import CapVideo, BaseVideo from weboob.capabilities.collection import CapCollection, CollectionNotFound, Collection from weboob.capabilities.cinema import CapCinema, Person, Movie @@ -27,7 +30,7 @@ from .browser import AllocineBrowser __all__ = ['AllocineModule'] -class AllocineModule(Module, CapCinema, CapVideo, CapCollection): +class AllocineModule(Module, CapCinema, CapVideo, CapCalendarEvent, CapCollection): NAME = 'allocine' MAINTAINER = u'Julien Veyssier' EMAIL = 'julien.veyssier@aiur.fr' @@ -35,6 +38,7 @@ class AllocineModule(Module, CapCinema, CapVideo, CapCollection): DESCRIPTION = u'AlloCiné French cinema database service' LICENSE = 'AGPLv3+' BROWSER = AllocineBrowser + ASSOCIATED_CATEGORIES = [CATEGORIES.CINE] def get_movie(self, id): return self.browser.get_movie(id) @@ -117,7 +121,7 @@ class AllocineModule(Module, CapCinema, CapVideo, CapCollection): video = self.get_video(self, video.id) if hasattr(video, '_video_code'): - video.url = self.browser.get_video_url(video._video_code) + video.url = unicode(self.browser.get_video_url(video._video_code)) if 'thumbnail' in fields and video and video.thumbnail: with self.browser: @@ -174,8 +178,29 @@ class AllocineModule(Module, CapCinema, CapVideo, CapCollection): raise CollectionNotFound(collection.split_path) + def search_events(self, query): + with self.browser: + if CATEGORIES.CINE in query.categories: + if query.city and re.match('\d{5}', query.city): + events = list(self.browser.search_events(query)) + events.sort(key=lambda x: x.start_date, reverse=False) + return events + else: + raise UserError('You must enter a zip code in city field') + + def get_event(self, id): + return self.browser.get_event(id) + + def fill_event(self, event, fields): + if 'description' in fields: + movieCode = event.id.split('#')[2] + movie = self.get_movie(movieCode) + event.description = movie.pitch + return event + OBJECTS = { Person: fill_person, Movie: fill_movie, - BaseVideo: fill_video + BaseVideo: fill_video, + BaseCalendarEvent: fill_event } diff --git a/modules/allocine/test.py b/modules/allocine/test.py index d9b1db79..57564292 100644 --- a/modules/allocine/test.py +++ b/modules/allocine/test.py @@ -19,6 +19,8 @@ from weboob.tools.test import BackendTest from weboob.capabilities.video import BaseVideo +from weboob.capabilities.calendar import Query, CATEGORIES +from datetime import datetime import re @@ -93,26 +95,39 @@ class AllocineTest(BackendTest): l1 = list(self.backend.iter_resources([BaseVideo], l[0].split_path)) assert len(l1) v = l1[0] - self.backend.fillobj(v, ('url',)) + self.backend.fillobj(v, 'url') self.assertTrue(v.url, 'URL for video "%s" not found' % (v.id)) def test_interview(self): l = list(self.backend.iter_resources([BaseVideo], [u'interview'])) assert len(l) v = l[0] - self.backend.fillobj(v, ('url',)) + self.backend.fillobj(v, 'url') self.assertTrue(v.url, 'URL for video "%s" not found' % (v.id)) def test_comingsoon(self): l = list(self.backend.iter_resources([BaseVideo], [u'comingsoon'])) assert len(l) v = l[0] - self.backend.fillobj(v, ('url',)) + self.backend.fillobj(v, 'url') self.assertTrue(v.url, 'URL for video "%s" not found' % (v.id)) def test_nowshowing(self): l = list(self.backend.iter_resources([BaseVideo], [u'nowshowing'])) assert len(l) v = l[0] - self.backend.fillobj(v, ('url',)) + self.backend.fillobj(v, 'url') self.assertTrue(v.url, 'URL for video "%s" not found' % (v.id)) + + def test_showtimelist(self): + query = Query() + query.city = u'59000' + query.categories = [CATEGORIES.CINE] + query.start_date = datetime.now() + l = self.backend.search_events(query) + assert len(l) + e = l[0] + self.backend.fillobj(e, 'description') + self.assertTrue(e.description, 'Description of "%s" not found' % (e.id)) + e = self.backend.get_event(e.id) + self.assertTrue(e.description, 'Description of "%s" not found' % (e.id))