def getTraktEpisodeInfo(showName, seasonNumber, episodeNumber, cache, seriesWhitelist, seriesMismatched): print showName, seasonNumber, episodeNumber if (showName.lower() in cache): showTvDbId = cache[showName.lower()]['tvdb'] showName = cache[showName.lower()]['title'] elif (showName in seriesMismatched): showRes = showName showName = seriesMismatched[showName] showTvDbId = TVShow('"' + showName + '"').tvdb cache = updateCache(cache, showRes, showName, showTvDbId) elif (showName in seriesWhitelist): showTvDbId = seriesWhitelist[showName] else: showName = showName.replace("(", "").replace(")", "").replace(":", "") showRes = TVShow.search('"' + showName + '"') for showFound in showRes: if showName.lower() == showFound.title.lower(): cache = updateCache(cache, showName, showFound.title, showFound.tvdb) showName = showFound.title showTvDbId = showFound.tvdb break else: # Cannot find exact show name in trakt.tv search results so use 1st entry cache = updateCache(cache, showName, showRes[0].title, showRes[0].tvdb) showName = showRes[0].title showTvDbId = showRes[0].tvdb print showName, showTvDbId, seasonNumber, episodeNumber episode = TVEpisode(showName, seasonNumber, episodeNumber) #print episode.show, showTvDbId, seasonNumber, episodeNumber, episode.title, episode.tvdb return (showName, showTvDbId, seasonNumber, episodeNumber, episode.title, episode.tvdb)
def _build(self, data): """Build the calendar""" self._calendar = [] for item in data: show_data = item.pop('show') episode_data = { **item.pop('episode'), 'airs_at': airs_date(item.get('first_aired')) } show = TVShow( show_data.pop('title'), slug="sodiafagiaugaiugh", **{ **show_data, # 'seasons': [] }) episode = TVEpisode(show.title, episode_data.pop('season'), episode_data.pop('number'), slug=show.slug, **episode_data) for season in show.seasons: if season.season != episode.season: continue season._episodes = [episode] show._seasons = [season] self._calendar.append(show) break self._calendar = sorted(self._calendar, key=lambda x: x.seasons[0].episodes[0].airs_at)
def test_rate_show(): got = TVShow('Game of Thrones') assert got.rate(10)['added'] == { 'episodes': 2, 'movies': 1, 'seasons': 1, 'shows': 1 }
def get_watched(list_type=None, extended=None): """Return all movies or shows a user has watched sorted by most plays. :param list_type: Optional Filter by a specific type. Possible values: movies, shows, seasons or episodes. :param extended: Optional value for requesting extended information. """ valid_type = ('movies', 'shows', 'seasons', 'episodes') if list_type and list_type not in valid_type: raise ValueError('list_type must be one of {}'.format(valid_type)) uri = 'sync/watchlist' if list_type: uri += '/{}'.format(list_type) if list_type == 'shows' and extended: uri += '?extended={extended}'.format(extended=extended) data = yield uri results = [] for d in data: if 'movie' in d: from trakt.movies import Movie results.append(Movie(**d.pop('movie'))) elif 'show' in d: from trakt.tv import TVShow results.append(TVShow(**d.pop('show'))) yield results
def search_by_id(query, id_type='imdb'): """Perform a search query by using a Trakt.tv ID or other external ID :param query: Your search string :param id_type: The type of object you're looking for. Must be one of 'trakt-movie', 'trakt-show', 'trakt-episode', 'imdb', 'tmdb', 'tvdb' or 'tvrage' """ valids = ('trakt-movie', 'trakt-show', 'trakt-episode', 'imdb', 'tmdb', 'tvdb', 'tvrage') if id_type not in valids: raise ValueError('search_type must be one of {}'.format(valids)) data = yield 'search?id={query}&id_type={id_type}'.format( query=slugify(query), id_type=id_type) for media_item in data: extract_ids(media_item) results = [] for d in data: if 'episode' in d: from trakt.tv import TVEpisode show = d.pop('show') extract_ids(d['episode']) results.append(TVEpisode(show['title'], **d['episode'])) elif 'movie' in d: from trakt.movies import Movie results.append(Movie(**d.pop('movie'))) elif 'show' in d: from trakt.tv import TVShow results.append(TVShow(**d.pop('show'))) elif 'person' in d: from trakt.people import Person results.append(Person(**d.pop('person'))) yield results
def get_collection(list_type=None, extended=None): """ Get all collected items in a user's collection. A collected item indicates availability to watch digitally or on physical media. :param list_type: Optional Filter by a specific type. Possible values: movies or shows. :param extended: Optional value for requesting extended information. """ valid_type = ('movies', 'shows') if list_type and list_type not in valid_type: raise ValueError('list_type must be one of {}'.format(valid_type)) uri = 'sync/watchlist' if list_type: uri += '/{}'.format(list_type) if extended: uri += '?extended={extended}'.format(extended=extended) data = yield uri results = [] for d in data: if 'movie' in d: from trakt.movies import Movie results.append(Movie(**d.pop('movie'))) elif 'show' in d: from trakt.tv import TVShow results.append(TVShow(**d.pop('show'))) yield results
def search_by_id(query, id_type='imdb', media_type=None): """Perform a search query by using a Trakt.tv ID or other external ID :param query: Your search string, which should be an ID from your source :param id_type: The source of the ID you're looking for. Must be one of 'trakt', trakt-movie', 'trakt-show', 'trakt-episode', 'trakt-person', 'imdb', 'tmdb', or 'tvdb' :param media_type: The type of media you're looking for. May be one of 'movie', 'show', 'episode', or 'person', or a comma-separated list of any combination of those. Null by default, which will return all types of media that match the ID given. """ valids = ('trakt', 'trakt-movie', 'trakt-show', 'trakt-episode', 'trakt-person', 'imdb', 'tmdb', 'tvdb') id_types = {'trakt': 'trakt', 'trakt-movie': 'trakt', 'trakt-show': 'trakt', 'trakt-episode': 'trakt', 'trakt-person': 'trakt', 'imdb': 'imdb', 'tmdb': 'tmdb', 'tvdb': 'tvdb'} if id_type not in valids: raise ValueError('search_type must be one of {}'.format(valids)) source = id_types.get(id_type) media_types = {'trakt-movie': 'movie', 'trakt-show': 'show', 'trakt-episode': 'episode', 'trakt-person': 'person'} # If there was no media_type passed in, see if we can guess based off the # ID source. None is still an option here, as that will return all possible # types for a given source. if media_type is None: media_type = media_types.get(source, None) # If media_type is still none, don't add it as a parameter to the search if media_type is None: uri = 'search/{source}/{query}'.format( query=slugify(query), source=source) else: uri = 'search/{source}/{query}?type={media_type}'.format( query=slugify(query), source=source, media_type=media_type) data = yield uri for media_item in data: extract_ids(media_item) results = [] for d in data: if 'episode' in d: from trakt.tv import TVEpisode show = d.pop('show') extract_ids(d['episode']) results.append(TVEpisode(show['title'], **d['episode'])) elif 'movie' in d: from trakt.movies import Movie results.append(Movie(**d.pop('movie'))) elif 'show' in d: from trakt.tv import TVShow results.append(TVShow(**d.pop('show'))) elif 'person' in d: from trakt.people import Person results.append(Person(**d.pop('person'))) yield results
def show_collection(self): """All :class:`TVShow`'s in this :class:`User`'s library collection. Collection items might include blu-rays, dvds, and digital downloads. Protected users won't return any data unless you are friends. """ if self._show_collection is None: ext = 'users/{username}/collection/shows?extended=metadata' data = yield ext.format(username=self.username) self._show_collection = [] for show in data: s = show.pop('show') extract_ids(s) sh = TVShow(**s) sh._seasons = [TVSeason(show=sh.title, **sea) for sea in show.pop('seasons')] self._show_collection.append(sh) yield self._show_collection
def test_oneliners(): got = TVShow('Game of Thrones') functions = [got.add_to_library, got.add_to_collection, got.add_to_watchlist, got.dismiss, got.mark_as_seen, got.mark_as_unseen, got.remove_from_library, got.remove_from_collection, got.remove_from_watchlist] for fn in functions: assert fn() is None
def search(query, search_type='movie', year=None): """Perform a search query against all of trakt's media types :param query: Your search string :param search_type: The type of object you're looking for. Must be one of 'movie', 'show', 'movie,show', 'episode', or 'person' """ valids = ('movie', 'show', 'episode', 'person', 'movie,show') if search_type not in valids: raise ValueError('search_type must be one of {}'.format(valids)) uri = 'search?query={query}&type={type}'.format( query=slugify(query), type=search_type) if year is not None: uri += '&year={}'.format(year) data = yield uri for media_item in data: extract_ids(media_item) # Need to do imports here to prevent circular imports with modules that # need to import Scrobblers if search_type == 'movie': from trakt.movies import Movie yield [Movie(d['score'], **d.pop('movie')) for d in data] elif search_type == 'show': from trakt.tv import TVShow yield [TVShow(d['score'], **d.pop('show')) for d in data] elif search_type == 'movie,show': from trakt.movies import Movie from trakt.tv import TVShow yield [Movie(d['score'], **d.pop('movie')) if d['type'] == 'movie' else TVShow(d['score'], **d.pop('show')) for d in data] elif search_type == 'episode': from trakt.tv import TVEpisode episodes = [] for episode in data: show = episode.pop('show') extract_ids(episode['episode']) episodes.append(TVEpisode(show.get('title', None), **episode['episode'])) yield episodes elif search_type == 'person': from trakt.people import Person yield [Person(**d.pop('person')) for d in data]
def test_get_show(): titles = ['Game of Thrones', 'game-of-thrones'] for title in titles: got = TVShow(title) images = got.images assert isinstance(images, dict) assert str(got) == '<TVShow> ' + got.title assert repr(got) == str(got)
def test_oneliners(tvshow_fn, get_key): got = TVShow('Game of Thrones') fn = getattr(got, tvshow_fn) response = fn() if get_key == 'skip': # The @deleted method, does not give back a result. assert response is None elif get_key in ('added', 'deleted'): assert response.get(get_key)
def trakt(self, title=None, year=None, country=None): from trakt import init, core core.OAUTH_TOKEN = u'bearer 46654942dd1e4d0ac76a4a3f133b5f9e47abcc80c6d307c645c395cf98a786a1' core.CLIENT_ID = '54d65f67401b045bc720ef109d4d05a107c0f5e28badf2f413f89f9bee514ae7' core.CLIENT_SECRET = '85f06b5b6d29265a8be4fa113bbaefb0dd58826cbfd4b85da9a709459a0cb9b1' from trakt.tv import TVShow it_crowd = TVShow(title) return
def watched_shows(self): """Watched profess for all :class:`TVShow`'s in this :class:`User`'s collection. """ if self._watched_shows is None: data = yield 'users/{user}/watched/shows'.format( user=slugify(self.username)) self._watched_shows = [] for show in data: show_data = show.pop('show') extract_ids(show_data) show_data.update(show) self._watched_shows.append(TVShow(**show_data)) yield self._watched_shows
def watchlist_shows(self): """Returns all watchlist shows of :class:`User`. """ if self._show_watchlist is None: data = yield 'users/{username}/watchlist/shows'.format( username=slugify(self.username), ) self._show_watchlist = [] for show in data: show_data = show.pop('show') extract_ids(show_data) show_data.update(show) self._show_watchlist.append(TVShow(**show_data)) yield self._show_watchlist yield self._show_watchlist
def get_search_results(query, search_type=None, slugify_query=False): """Perform a search query against all of trakt's media types. :param query: Your search string :param search_type: The types of objects you're looking for. Must be specified as a list of strings containing any of 'movie', 'show', 'episode', or 'person'. :param slugify_query: A boolean indicating whether or not the provided query should be slugified or not prior to executing the query. """ # if no search type was specified, then search everything if search_type is None: search_type = ['movie', 'show', 'episode', 'person'] # If requested, slugify the query prior to running the search if slugify_query: query = slugify(query) uri = 'search/{type}?query={query}'.format( query=query, type=','.join(search_type)) data = yield uri # Need to do imports here to prevent circular imports with modules that # need to import Scrobblers results = [] for media_item in data: extract_ids(media_item) result = SearchResult(media_item['type'], media_item['score']) if media_item['type'] == 'movie': from trakt.movies import Movie result.media = Movie(**media_item.pop('movie')) elif media_item['type'] == 'show': from trakt.tv import TVShow result.media = TVShow(**media_item.pop('show')) elif media_item['type'] == 'episode': from trakt.tv import TVEpisode show = media_item.pop('show') result.media = TVEpisode(show.get('title', None), **media_item.pop('episode')) elif media_item['type'] == 'person': from trakt.people import Person result.media = Person(**media_item.pop('person')) results.append(result) yield results
def _search(self, query): """Search Trakt for a TV episode matching *query*""" results = TVShow.search(query) self.filter_key = slugify(query) result = self.filter_results(query, results) if result is None: return self.context show = TVShow(result.slug) LOGGER.info('Trakt Search Result: %s', str(show)) self._apply_mapping(show) # Get general information about the show # Get episode specific data season_num = self.context.get('TV Season', None) if season_num is None: return self.context episode_num = self.context.get('TV Episode #') episode = TVEpisode(result.slug, season_num, episode_num) return self._get_episode(episode)
def do_trakt_search(self): """Search Trakt.TV for data on the episode being tagged""" self._update_progress() show_name = self.atoms['TV Show'] season_num = int(self.atoms['TV Season']) if int(self.atoms.get('TV Episode #', 0)) != 0: episode_num = int(self.atoms['TV Episode #']) - 1 else: episode_num = int(self.atoms['TV Episode #']) msg = u'{} : {} : {}'.format(show_name, season_num, episode_num) self.logger.warning(msg) show = TVShow(show_name) episode = show.seasons[season_num].episodes[episode_num] self.atoms['Rating'] = show.certification self.atoms['Genre'] = show.genres[0].name self.atoms['TV Network'] = show.network actors = [] for actor in show.people: if hasattr(actor, 'name'): actors.append(actor.name) self.atoms['Cast'] = ', '.join([actor for actor in actors if actor is not None]) self.atoms['Release Date'] = episode.first_aired_iso if len(episode.overview) > 250: self.atoms['Description'] = episode.overview[:250] else: self.atoms['Description'] = episode.overview self.atoms['Long Description'] = episode.overview self.atoms['TV Show'] = episode.show self.atoms['Artist'] = episode.show self.atoms['Name'] = episode.title # Reformat fields self.atoms['Album Artist'] = episode.show # Reformat album name self.atoms['Album'] = '{}, Season {}'.format(self.atoms['Artist'], self.atoms['TV Season']) if self.atoms['Genre'] in TV_GENREIDS: self.atoms['genreID'] = TV_GENREIDS[self.atoms['Genre']] self._update_progress()
def get_watchlist(list_type=None, sort=None): """ Get a watchlist. optionally with a filter for a specific item type. :param list_type: Optional Filter by a specific type. Possible values: movies, shows, seasons or episodes. :param sort: Optional sort. Only if the type is also sent. Possible values: rank, added, released or title. """ valid_type = ('movies', 'shows', 'seasons', 'episodes') valid_sort = ('rank', 'added', 'released', 'title') if list_type and list_type not in valid_type: raise ValueError('list_type must be one of {}'.format(valid_type)) if sort and sort not in valid_sort: raise ValueError('sort must be one of {}'.format(valid_sort)) uri = 'sync/watchlist' if list_type: uri += '/{}'.format(list_type) if list_type and sort: uri += '/{}'.format(sort) data = yield uri results = [] for d in data: if 'episode' in d: from trakt.tv import TVEpisode show = d.pop('show') extract_ids(d['episode']) results.append(TVEpisode(show, **d['episode'])) elif 'movie' in d: from trakt.movies import Movie results.append(Movie(**d.pop('movie'))) elif 'show' in d: from trakt.tv import TVShow results.append(TVShow(**d.pop('show'))) yield results
def get_items(self): """A list of the list items using class instances instance types: movie, show, season, episode, person """ data = yield 'users/{user}/lists/{id}/items'.format(user=slugify( self.creator), id=self.slug) for item in data: # match list item type if 'type' not in item: continue item_type = item['type'] item_data = item.pop(item_type) extract_ids(item_data) if item_type == 'movie': self._items.append( Movie(item_data['title'], item_data['year'], item_data['slug'])) elif item_type == 'show': self._items.append( TVShow(item_data['title'], item_data['slug'])) elif item_type == 'season': show_data = item.pop('show') extract_ids(show_data) season = TVSeason(show_data['title'], item_data['number'], show_data['slug']) self._items.append(season) elif item_type == 'episode': show_data = item.pop('show') extract_ids(show_data) episode = TVEpisode(show_data['title'], item_data['season'], item_data['number']) self._items.append(episode) elif item_type == 'person': self._items.append(Person(item_data['name'], item_data['slug'])) yield self._items
def _build(self, data): """Build the calendar""" self._calendar = [] for cal_item in data: show_data = cal_item.get('show', {}) episode = cal_item.get('episode', {}) first_aired = cal_item.get('first_aired') season = episode.get('season') ep_num = episode.get('number') extract_ids(show_data) show_data.update(show_data) e_data = { 'airs_at': airs_date(first_aired), 'ids': episode.get('ids'), 'title': show_data.get('title'), 'show_data': TVShow(**show_data) } self._calendar.append( TVEpisode(show_data['trakt'], season, ep_num, **e_data) ) self._calendar = sorted(self._calendar, key=lambda x: x.airs_at)
def _extract_media(self, media): from trakt.tv import TVShow data = media.get(self.MEDIA_KEY) return TVShow(**data)
def update(self): """Get the latest state of the sensor.""" from trakt.calendar import MyShowCalendar from trakt.tv import TVShow import requests attributes = {} default = {} card_json = [] default['title_default'] = '$title' default['line1_default'] = '$episode' default['line2_default'] = '$release' default['line3_default'] = '$rating - $runtime' default['line4_default'] = '$number - $studio' default['icon'] = 'mdi:arrow-down-bold' card_json.append(default) calendar = MyShowCalendar(days=self._days) if not calendar: _LOGGER.error("Nothing in upcoming calendar") return False self._state = len(calendar) for show in calendar: if not show or show.show in self._exclude: continue try: show_details = TVShow.search(show.show, show.year) except AttributeError: _LOGGER.error('Unable to retrieve show details for ' + show.show) if not show_details: continue session = requests.Session() try: tmdb_url = session.get( 'http://api.tmdb.org/3/tv/{}?api_key=0eee347e2333d7a97b724106353ca42f' .format(str(show_details[0].tmdb))) tmdb_json = tmdb_url.json() except requests.exceptions.RequestException as e: _LOGGER.warning('api.themoviedb.org is not responding') return image_url = 'https://image.tmdb.org/t/p/w%s%s' if days_until(show.airs_at.isoformat() + 'Z', self._tz) <= 7: release = '$day, $time' else: release = '$day, $date $time' card_item = { 'airdate': show.airs_at.isoformat() + 'Z', 'release': release, 'flag': False, 'title': show.show, 'episode': show.title, 'number': 'S' + str(show.season) + 'E' + str(show.number), 'rating': tmdb_json.get('vote_average', ''), 'poster': image_url % ('500', tmdb_json.get('poster_path', '')), 'fanart': image_url % ('780', tmdb_json.get('backdrop_path', '')), 'runtime': tmdb_json.get('episode_run_time')[0] if len(tmdb_json.get('episode_run_time')) > 0 else '', 'studio': tmdb_json.get('networks')[0].get('name', '') if len(tmdb_json.get('networks')) > 0 else '' } card_json.append(card_item) attributes['data'] = json.dumps(card_json) self._hass.data[DATA_UPCOMING] = attributes
def test_show_search_with_year(): results = TVShow.search('batman', year=1999) assert isinstance(results, list) assert len(results) == 10 assert all(isinstance(m, TVShow) for m in results)
def test_show_ids(): got = TVShow('Game of Thrones') assert isinstance(got.ids, dict)
def test_watching(): got = TVShow('Game of Thrones') assert all(isinstance(u, User) for u in got.watching_now)
def test_show_search(): results = TVShow.search('batman') assert isinstance(results, list) assert all(isinstance(m, TVShow) for m in results)
def test_related(): got = TVShow('Game of Thrones') assert all(isinstance(s, TVShow) for s in got.related)
def test_ratings(): got = TVShow('Game of Thrones') assert isinstance(got.ratings, dict)
def test_show_search_with_year(): results = TVShow.search('batman', year=1999) assert isinstance(results, list) assert len(results) == 1 assert all(isinstance(m, TVShow) for m in results)
def test_translations(): got = TVShow('Game of Thrones') translations = got.get_translations('es') assert isinstance(translations, list) assert len(translations) == 3
def test_get_comments(): got = TVShow('Game of Thrones') assert all(isinstance(c, Comment) for c in got.comments) assert len(got.comments) == 1
def test_get_people(): got = TVShow('Game of Thrones') assert isinstance(got.people, list) groups = [got.people, got.cast, got.crew] for group in groups: assert all([isinstance(p, Person) for p in group])
def test_rate_show(): got = TVShow('Game of Thrones') got.rate(10)
def test_show_comment(): got = TVShow('Game of Thrones') got.comment('Test Comment Data')