def add_show_trakt_library(self, show_obj): """Add show to trakt library.""" data = {} if not self.find_show(show_obj.indexerid, show_obj.indexer): # Check if TRAKT supports that indexer if not get_trakt_indexer(show_obj.indexer): return # URL parameters title = get_title_without_year(show_obj.name, show_obj.start_year) data = { 'shows': [ { 'title': title, 'year': show_obj.start_year, 'ids': {} } ] } data['shows'][0]['ids'][get_trakt_indexer(show_obj.indexer)] = show_obj.indexerid if data: log.info("Adding show '{show}' to Trakt library", {'show': show_obj.name}) try: self._request('sync/collection', data, method='POST') except (TraktException, AuthException, TokenExpiredException) as e: log.info("Unable to add show '{show}' to Trakt library. Error: {error}", { 'show': show_obj.name, 'error': e.message }) return
def _check_list(self, show_obj=None, indexer=None, indexer_id=None, season=None, episode=None, list_type=None): """Check if we can find the show in the Trakt watchlist|collection list.""" if 'Collection' == list_type: trakt_indexer = get_trakt_indexer(indexer) for collected_show in self.collection_list: if not getattr(collected_show, trakt_indexer) == indexer_id: continue if 'seasons' in collected_show: for season_item in collected_show['seasons']: for episode_item in season_item['episodes']: trakt_season = season_item['number'] trakt_episode = episode_item['number'] if trakt_season == season and trakt_episode == episode: return True else: return False elif 'Show' == list_type: trakt_indexer = get_trakt_indexer(show_obj.indexer) for watchlisted_show in self.show_watchlist: if getattr(watchlisted_show, trakt_indexer) == show_obj.indexerid or \ getattr(watchlisted_show, get_trakt_indexer(EXTERNAL_IMDB)) == show_obj.imdb_id: return True return False else: trakt_indexer = get_trakt_indexer(indexer) for watchlisted_episode in self.episode_watchlist: if watchlisted_episode.season == season and \ watchlisted_episode.episode == episode and \ watchlisted_episode['ids'].get(trakt_indexer) == indexer_id: return True return False
def add_show_trakt_library(self, show_obj): """Add show to trakt library.""" data = {} if not self.find_show(show_obj.indexerid, show_obj.indexer): # Check if TRAKT supports that indexer if not get_trakt_indexer(show_obj.indexer): return # URL parameters title = get_title_without_year(show_obj.name, show_obj.start_year) data = { 'shows': [ { 'title': title, 'year': show_obj.start_year, 'ids': {} } ] } data['shows'][0]['ids'][get_trakt_indexer(show_obj.indexer)] = show_obj.indexerid if data: log.info("Adding show '{show}' to Trakt library", {'show': show_obj.name}) try: self._request('sync/collection', data, method='POST') except (TraktException, AuthException, TokenExpiredException) as error: log.info("Unable to add show '{show}' to Trakt library. Error: {error!r}", { 'show': show_obj.name, 'error': error }) return
def _check_list(self, show_obj=None, indexer=None, indexer_id=None, season=None, episode=None, list_type=None): """Check if we can find the show in the Trakt watchlist|collection list.""" if 'Collection' == list_type: trakt_indexer = get_trakt_indexer(indexer) for collected_show in self.collection_list: if not collected_show['show']['ids'].get(trakt_indexer, '') == indexer_id: continue if 'seasons' in collected_show: for season_item in collected_show['seasons']: for episode_item in season_item['episodes']: trakt_season = season_item['number'] trakt_episode = episode_item['number'] if trakt_season == season and trakt_episode == episode: return True else: return False elif 'Show' == list_type: trakt_indexer = get_trakt_indexer(show_obj.indexer) for watchlisted_show in self.show_watchlist: if watchlisted_show['show']['ids'].get(trakt_indexer) == show_obj.indexerid or \ watchlisted_show['show']['ids'].get(get_trakt_indexer(EXTERNAL_IMDB), '') == show_obj.imdb_id: return True return False else: trakt_indexer = get_trakt_indexer(indexer) for watchlisted_episode in self.episode_watchlist: if watchlisted_episode['episode'].get('season', -1) == season and \ watchlisted_episode['episode'].get('number', -1) == episode and \ watchlisted_episode['show']['ids'].get(trakt_indexer, '') == indexer_id: return True return False
def sync_trakt_shows(self): """Sync Trakt shows watchlist.""" if not self.show_watchlist: log.info('No shows found in your Trakt watchlist. Nothing to sync') return trakt_default_indexer = int(app.TRAKT_DEFAULT_INDEXER) for trakt_show in self.show_watchlist: if trakt_show.year and trakt_show.ids['ids']['slug'].endswith( str(trakt_show.year)): show_name = f'{trakt_show.title} ({trakt_show.year})' else: show_name = trakt_show.title show = None indexer = None for i in indexerConfig: trakt_indexer = get_trakt_indexer(i) indexer_id = trakt_show.ids['ids'].get(trakt_indexer, -1) indexer = indexerConfig[i]['id'] show = Show.find_by_id(app.showList, indexer, indexer_id) if show: break if not show: # If can't find with available indexers try IMDB trakt_indexer = get_trakt_indexer(EXTERNAL_IMDB) indexer_id = trakt_show.ids['ids'].get(trakt_indexer, -1) show = Show.find_by_id(app.showList, EXTERNAL_IMDB, indexer_id) if not show: # If can't find with available indexers try TRAKT trakt_indexer = get_trakt_indexer(EXTERNAL_TRAKT) indexer_id = trakt_show.ids['ids'].get(trakt_indexer, -1) show = Show.find_by_id(app.showList, EXTERNAL_TRAKT, indexer_id) if show: continue indexer_id = trakt_show.ids['ids'].get( get_trakt_indexer(trakt_default_indexer), -1) if int(app.TRAKT_METHOD_ADD) != 2: self.add_show(trakt_default_indexer, indexer_id, show_name, SKIPPED) else: self.add_show(trakt_default_indexer, indexer_id, show_name, WANTED) if int(app.TRAKT_METHOD_ADD) == 1 and indexer: new_show = Show.find_by_id(app.showList, indexer, indexer_id) if new_show: set_episode_to_wanted(new_show, 1, 1) else: log.warning( 'Unable to find the new added show.' 'Pilot will be set to wanted in the next Trakt run') self.todo_wanted.append((indexer, indexer_id, 1, 1)) log.debug('Synced shows with Trakt watchlist')
def sync_trakt_shows(self): """Sync Trakt shows watchlist.""" if not self.show_watchlist: log.info('No shows found in your Trakt watchlist. Nothing to sync') else: trakt_default_indexer = int(app.TRAKT_DEFAULT_INDEXER) for watchlisted_show in self.show_watchlist: trakt_show = watchlisted_show['show'] if trakt_show['year'] and trakt_show['ids']['slug'].endswith(str(trakt_show['year'])): show_name = '{title} ({year})'.format(title=trakt_show['title'], year=trakt_show['year']) else: show_name = trakt_show['title'] show = None indexer = None for i in indexerConfig: trakt_indexer = get_trakt_indexer(i) indexer_id = trakt_show['ids'].get(trakt_indexer, -1) indexer = indexerConfig[i]['id'] show = Show.find_by_id(app.showList, indexer, indexer_id) if show: break if not show: # If can't find with available indexers try IMDB trakt_indexer = get_trakt_indexer(EXTERNAL_IMDB) indexer_id = trakt_show['ids'].get(trakt_indexer, -1) show = Show.find_by_id(app.showList, EXTERNAL_IMDB, indexer_id) if not show: # If can't find with available indexers try TRAKT trakt_indexer = get_trakt_indexer(EXTERNAL_TRAKT) indexer_id = trakt_show['ids'].get(trakt_indexer, -1) show = Show.find_by_id(app.showList, EXTERNAL_TRAKT, indexer_id) if show: continue indexer_id = trakt_show['ids'].get(get_trakt_indexer(trakt_default_indexer), -1) if int(app.TRAKT_METHOD_ADD) != 2: self.add_show(trakt_default_indexer, indexer_id, show_name, SKIPPED) else: self.add_show(trakt_default_indexer, indexer_id, show_name, WANTED) if int(app.TRAKT_METHOD_ADD) == 1 and indexer: new_show = Show.find_by_id(app.showList, indexer, indexer_id) if new_show: set_episode_to_wanted(new_show, 1, 1) else: log.warning('Unable to find the new added show.' 'Pilot will be set to wanted in the next Trakt run') self.todoWanted.append(indexer_id) log.debug('Synced shows with Trakt watchlist')
def sync_trakt_episodes(self): """Sync Trakt episodes watchlist.""" if not self.episode_watchlist: log.info( 'No episodes found in your Trakt watchlist. Nothing to sync') return added_shows = [] trakt_default_indexer = int(app.TRAKT_DEFAULT_INDEXER) for watchlist_item in self.episode_watchlist: trakt_show = watchlist_item.show trakt_episode = watchlist_item.episode trakt_season = watchlist_item.season show = None for i in indexerConfig: trakt_indexer = get_trakt_indexer(i) if not trakt_indexer: continue indexer_id = trakt_show['ids'].get(trakt_indexer, -1) indexer = indexerConfig[i]['id'] show = Show.find_by_id(app.showList, indexer, indexer_id) if show: break if not show: # If can't find with available indexers try IMDB trakt_indexer = get_trakt_indexer(EXTERNAL_IMDB) indexer_id = trakt_show['ids'].get(trakt_indexer, -1) show = Show.find_by_id(app.showList, EXTERNAL_IMDB, indexer_id) if not show: # If can't find with available indexers try TRAKT trakt_indexer = get_trakt_indexer(EXTERNAL_TRAKT) indexer_id = trakt_show['ids'].get(trakt_indexer, -1) show = Show.find_by_id(app.showList, EXTERNAL_TRAKT, indexer_id) # If can't find show add with default trakt indexer if not show: trakt_indexer = get_trakt_indexer(trakt_default_indexer) indexer_id = trakt_show['ids'].get(trakt_indexer, -1) # Only add show if we didn't added it before if indexer_id not in added_shows: self.add_show(trakt_default_indexer, indexer_id, trakt_show['title'], SKIPPED) added_shows.append(indexer_id) elif not trakt_season == 0 and not show.paused: set_episode_to_wanted(show, trakt_season, trakt_episode) log.debug('Synced episodes with Trakt watchlist')
def add_show_trakt_library(self, show_obj): """Add show to trakt library.""" if self.find_show(show_obj.indexerid, show_obj.indexer): return # Check if TRAKT supports that indexer if not get_trakt_indexer(show_obj.indexer): return log.info("Adding show '{show}' to Trakt library", {'show': show_obj.name}) try: result = sync.add_to_collection(create_show_structure(show_obj)) except TraktException as error: log.info("Unable to add show '{show}' to Trakt library. Error: {error!r}", { 'show': show_obj.name, 'error': error }) return if result and (result.get('added') or result.get('existing')): if result['added']['shows']: return True return False
def remove_show_trakt_library(self, show_obj): """Remove show from trakt library.""" if self.find_show(show_obj.indexerid, show_obj.indexer): # Check if TRAKT supports that indexer if not get_trakt_indexer(show_obj.indexer): return log.info("Removing '{show}' from Trakt library", {'show': show_obj.name}) # Remove all episodes from the Trakt collection for this show try: self.remove_episode_trakt_collection(filter_show=show_obj) except TraktException as error: log.info("Unable to remove all episodes from show '{show}' from Trakt library. Error: {error!r}", { 'show': show_obj.name, 'error': error }) try: sync.remove_from_collection(create_show_structure(show_obj)) except TraktException as error: log.info("Unable to remove show '{show}' from Trakt library. Error: {error!r}", { 'show': show_obj.name, 'error': error })
def remove_episode_watchlist(self): """Remove episode from Trakt watchlist.""" if not (app.TRAKT_SYNC_WATCHLIST and app.USE_TRAKT): return main_db_con = db.DBConnection() statuses = [DOWNLOADED, ARCHIVED] sql_selection = 'SELECT s.indexer, s.startyear, s.indexer_id, s.show_name, e.season, e.episode ' \ 'FROM tv_episodes AS e, tv_shows AS s ' \ 'WHERE e.indexer = s.indexer ' \ 'AND s.indexer_id = e.showid AND e.status in ({0})'.format(','.join(['?'] * len(statuses))) sql_result = main_db_con.select(sql_selection, statuses) if not sql_result: return episodes = [] shows = {} for cur_episode in sql_result: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode['indexer']): continue show_id = cur_episode['indexer'], cur_episode['indexer_id'] episode = cur_episode['season'], cur_episode['episode'] if show_id not in shows: shows[show_id] = [] shows[show_id].append(episode) media_object_shows = [] for show_id in shows: episodes = [] show_obj = Show.find_by_id(app.showList, show_id[0], show_id[1]) for season, episode in shows[show_id]: if not self._check_list(indexer=show_obj.indexer, indexer_id=show_obj.series_id, season=season, episode=episode, list_type='Collection'): continue log.info("Removing episode '{show}' {ep} from Trakt watchlist", { 'show': show_obj.name, 'ep': episode_num(season, episode) }) episodes.append(show_obj.get_episode(season, episode)) media_object_shows.append( create_episode_structure(show_obj, episodes)) try: sync.remove_from_collection({'shows': media_object_shows}) self._get_episode_watchlist() except TraktException as error: log.info( 'Unable to remove episodes from Trakt watchlist. Error: {error!r}', {'error': error})
def find_show(self, indexerid, indexer): """Find show in Trakt library.""" trakt_library = [] try: trakt_library = self._request('sync/collection/shows') except (TraktException, AuthException, TokenExpiredException) as e: log.info('Unable to retrieve shows from Trakt collection. Error: {error}', {'error': e.message}) if not trakt_library: log.info('No shows found in your Trakt library. Nothing to sync') return trakt_show = [x for x in trakt_library if get_trakt_indexer(indexer) and int(indexerid) in [int(x['show']['ids'].get(get_trakt_indexer(indexer)))]] return trakt_show if trakt_show else None
def find_show(self, indexerid, indexer): """Find show in Trakt library.""" trakt_library = [] try: trakt_library = self._request('sync/collection/shows') except (TraktException, AuthException, TokenExpiredException) as error: log.info('Unable to retrieve shows from Trakt collection. Error: {error!r}', {'error': error}) if not trakt_library: log.info('No shows found in your Trakt library. Nothing to sync') return trakt_show = [x for x in trakt_library if get_trakt_indexer(indexer) and int(indexerid) in [int(x['show']['ids'].get(get_trakt_indexer(indexer)))]] return trakt_show if trakt_show else None
def _check_list(self, show_obj=None, indexer=None, indexer_id=None, season=None, episode=None, list_type=None): """Check if we can find the show in the Trakt watchlist|collection list.""" def match_trakt_by_id(trakt_show, medusa_show): """Try to match the trakt show object to a Medusa show.""" trakt_supported_indexer = get_trakt_indexer(show_obj.indexer) if trakt_supported_indexer and getattr( trakt_show, trakt_supported_indexer) == medusa_show.indexerid: return True # Try to match by imdb_id if getattr(trakt_show, 'imdb') == medusa_show.imdb_id: return True return False if 'Collection' == list_type: trakt_indexer = get_trakt_indexer(indexer) for collected_show in self.collection_list: if not getattr(collected_show, trakt_indexer) == indexer_id: continue if hasattr(collected_show, 'seasons'): for season_item in collected_show.seasons: for episode_item in season_item.episodes: trakt_season = season_item.number trakt_episode = episode_item.number if trakt_season == season and trakt_episode == episode: return True else: return False elif 'Show' == list_type: for watchlisted_show in self.show_watchlist: if match_trakt_by_id(watchlisted_show, show_obj): return True return False else: trakt_indexer = get_trakt_indexer(indexer) for watchlisted_episode in self.episode_watchlist: if watchlisted_episode.season == season and \ watchlisted_episode.episode == episode and \ watchlisted_episode['ids'].get(trakt_indexer) == indexer_id: return True return False
def add_episode_trakt_collection(self): """Add all existing episodes to Trakt collections. For episodes that have a media file (location) """ if app.TRAKT_SYNC and app.USE_TRAKT: main_db_con = db.DBConnection() statuses = [DOWNLOADED, ARCHIVED] sql_selection = b'SELECT s.indexer, s.startyear, s.indexer_id, s.show_name, e.season, e.episode ' \ b'FROM tv_episodes AS e, tv_shows AS s ' \ b'WHERE e.indexer = s.indexer AND s.indexer_id = e.showid ' \ b"AND e.status in ({0}) AND e.location <> ''".format(','.join(['?'] * len(statuses))) sql_result = main_db_con.select(sql_selection, statuses) episodes = [dict(e) for e in sql_result] if episodes: trakt_data = [] for cur_episode in episodes: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode[b'indexer']): continue if not self._check_list( indexer=cur_episode[b'indexer'], indexer_id=cur_episode[b'indexer_id'], season=cur_episode[b'season'], episode=cur_episode[b'episode'], list_type='Collection'): log.info( "Adding episode '{show}' {ep} to Trakt collection", { 'show': cur_episode[b'show_name'], 'ep': episode_num(cur_episode[b'season'], cur_episode[b'episode']) }) title = get_title_without_year( cur_episode[b'show_name'], cur_episode[b'startyear']) trakt_data.append( (cur_episode[b'indexer_id'], cur_episode[b'indexer'], title, cur_episode[b'startyear'], cur_episode[b'season'], cur_episode[b'episode'])) if trakt_data: try: data = self.trakt_bulk_data_generate(trakt_data) self._request('sync/collection', data, method='POST') self._get_show_collection() except (TraktException, AuthException, TokenExpiredException) as e: log.info( 'Unable to add episodes to Trakt collection. Error: {error}', {'error': e.message})
def sync_trakt_episodes(self): """Sync Trakt episodes watchlist.""" if not self.episode_watchlist: log.info('No episodes found in your Trakt watchlist. Nothing to sync') return added_shows = [] trakt_default_indexer = int(app.TRAKT_DEFAULT_INDEXER) for watchlist_item in self.episode_watchlist: trakt_show = watchlist_item['show'] trakt_episode = watchlist_item['episode'].get('number', -1) trakt_season = watchlist_item['episode'].get('season', -1) show = None for i in indexerConfig: trakt_indexer = get_trakt_indexer(i) indexer_id = trakt_show['ids'].get(trakt_indexer, -1) indexer = indexerConfig[i]['id'] show = Show.find_by_id(app.showList, indexer, indexer_id) if show: break if not show: # If can't find with available indexers try IMDB trakt_indexer = get_trakt_indexer(EXTERNAL_IMDB) indexer_id = trakt_show['ids'].get(trakt_indexer, -1) show = Show.find_by_id(app.showList, EXTERNAL_IMDB, indexer_id) if not show: # If can't find with available indexers try TRAKT trakt_indexer = get_trakt_indexer(EXTERNAL_TRAKT) indexer_id = trakt_show['ids'].get(trakt_indexer, -1) show = Show.find_by_id(app.showList, EXTERNAL_TRAKT, indexer_id) # If can't find show add with default trakt indexer if not show: indexer_id = trakt_show['ids'].get(get_trakt_indexer(trakt_default_indexer), -1) # Only add show if we didn't added it before if indexer_id not in added_shows: self.add_show(trakt_default_indexer, indexer_id, trakt_show['title'], SKIPPED) added_shows.append(indexer_id) elif not trakt_season == 0 and not show.paused: set_episode_to_wanted(show, trakt_season, trakt_episode) log.debug('Synced episodes with Trakt watchlist')
def remove_show_trakt_library(self, show_obj): """Remove show from trakt library.""" if self.find_show(show_obj.indexerid, show_obj.indexer): # Check if TRAKT supports that indexer if not get_trakt_indexer(show_obj.indexer): return # URL parameters title = get_title_without_year(show_obj.name, show_obj.start_year) data = { 'shows': [{ 'title': title, 'year': show_obj.start_year, 'ids': {} }] } data['shows'][0]['ids'][get_trakt_indexer( show_obj.indexer)] = show_obj.indexerid log.info("Removing '{show}' from Trakt library", {'show': show_obj.name}) # Remove all episodes from the Trakt collection for this show try: self.remove_episode_trakt_collection(filter_show=show_obj) except (TraktException, AuthException, TokenExpiredException) as error: log.info( "Unable to remove all episodes from show '{show}' from Trakt library. Error: {error!r}", { 'show': show_obj.name, 'error': error }) try: self._request('sync/collection/remove', data, method='POST') except (TraktException, AuthException, TokenExpiredException) as error: log.info( "Unable to remove show '{show}' from Trakt library. Error: {error!r}", { 'show': show_obj.name, 'error': error })
def find_show(self, indexerid, indexer): """Find show in Trakt library.""" trakt_library = [] try: trakt_library = sync.get_collection('shows') except (TraktException, RequestException) as error: log.info('Unable to retrieve shows from Trakt collection. Error: {error!r}', {'error': error}) if not trakt_library: log.info('No shows found in your Trakt library. Nothing to sync') return trakt_show = [show for show in trakt_library if get_trakt_indexer(indexer) and show.ids['ids'].get(get_trakt_indexer(indexer)) and indexerid in [show.ids['ids'].get(get_trakt_indexer(indexer))]] return trakt_show if trakt_show else None
def add_episode_trakt_collection(self): """Add all existing episodes to Trakt collections. For episodes that have a media file (location) """ if not(app.TRAKT_SYNC and app.USE_TRAKT): return main_db_con = db.DBConnection() statuses = [DOWNLOADED, ARCHIVED] sql_selection = 'SELECT s.indexer, s.startyear, s.indexer_id, s.show_name, e.season, e.episode ' \ 'FROM tv_episodes AS e, tv_shows AS s ' \ 'WHERE e.indexer = s.indexer AND s.indexer_id = e.showid ' \ "AND e.status in ({0}) AND e.location <> ''".format(','.join(['?'] * len(statuses))) sql_result = main_db_con.select(sql_selection, statuses) if not sql_result: return episodes = [] shows = {} for cur_episode in sql_result: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode['indexer']): continue show_id = cur_episode['indexer'], cur_episode['indexer_id'] episode = cur_episode['season'], cur_episode['episode'] if show_id not in shows: shows[show_id] = [] shows[show_id].append(episode) media_object_shows = [] for show_id in shows: episodes = [] show_obj = Show.find_by_id(app.showList, show_id[0], show_id[1]) for season, episode in shows[show_id]: if not self._check_list( indexer=show_obj.indexer, indexer_id=show_obj.series_id, season=season, episode=episode, list_type='Collection' ): continue log.info("Adding episode '{show}' {ep} to Trakt collection", { 'show': show_obj.name, 'ep': episode_num(season, episode) }) episodes.append(show_obj.get_episode(season, episode)) media_object_shows.append(create_episode_structure(show_obj, episodes)) try: sync.add_to_collection({'shows': media_object_shows}) self._get_show_collection() except (TraktException, RequestException) as error: log.info('Unable to add episodes to Trakt collection. Error: {error!r}', {'error': error})
def match_trakt_by_id(trakt_show, medusa_show): """Try to match the trakt show object to a Medusa show.""" trakt_supported_indexer = get_trakt_indexer(show_obj.indexer) if trakt_supported_indexer and getattr(trakt_show, trakt_supported_indexer) == medusa_show.indexerid: return True # Try to match by imdb_id if getattr(trakt_show, 'imdb') == ImdbIdentifier(medusa_show.imdb_id).imdb_id: return True return False
def update_library(ep_obj): """Send a request to trakt indicating that the given episode is part of our library. ep_obj: The Episode object to add to trakt """ # Check if TRAKT supports that indexer if not get_trakt_indexer(ep_obj.series.indexer): return if app.USE_TRAKT: try: # URL parameters title = get_title_without_year(ep_obj.series.name, ep_obj.series.start_year) data = { 'shows': [{ 'title': title, 'year': ep_obj.series.start_year, 'ids': {}, }] } data['shows'][0]['ids'][get_trakt_indexer( ep_obj.series.indexer)] = ep_obj.series.indexerid # Add Season and Episode + Related Episodes data['shows'][0]['seasons'] = [{ 'number': ep_obj.season, 'episodes': [] }] for rel_ep_obj in [ep_obj] + ep_obj.related_episodes: data['shows'][0]['seasons'][0]['episodes'].append( {'number': rel_ep_obj.episode}) if app.TRAKT_SYNC_WATCHLIST: if app.TRAKT_REMOVE_SERIESLIST: sync.remove_from_watchlist(data) # update library sync.add_to_collection(data) except (TraktException, RequestException) as error: log.warning('Unable to update Trakt: {error!r}', {'error': error})
def remove_episode_watchlist(self): """Remove episode from Trakt watchlist.""" if app.TRAKT_SYNC_WATCHLIST and app.USE_TRAKT: main_db_con = db.DBConnection() statuses = [DOWNLOADED, ARCHIVED] sql_selection = b'SELECT s.indexer, s.startyear, e.showid, s.show_name, e.season, e.episode ' \ b'FROM tv_episodes AS e, tv_shows AS s ' \ b'WHERE e.indexer = s.indexer ' \ b'AND s.indexer_id = e.showid AND e.status in ({0})'.format(','.join(['?'] * len(statuses))) sql_result = main_db_con.select(sql_selection, statuses) episodes = [dict(i) for i in sql_result] if episodes: trakt_data = [] for cur_episode in episodes: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode[b'indexer']): continue if self._check_list(indexer=cur_episode[b'indexer'], indexer_id=cur_episode[b'showid'], season=cur_episode[b'season'], episode=cur_episode[b'episode']): log.info( "Removing episode '{show}' {ep} from Trakt watchlist", { 'show': cur_episode[b'show_name'], 'ep': episode_num(cur_episode[b'season'], cur_episode[b'episode']) }) title = get_title_without_year( cur_episode[b'show_name'], cur_episode[b'startyear']) trakt_data.append( (cur_episode[b'showid'], cur_episode[b'indexer'], title, cur_episode[b'startyear'], cur_episode[b'season'], cur_episode[b'episode'])) if trakt_data: try: data = self.trakt_bulk_data_generate(trakt_data) self._request('sync/watchlist/remove', data, method='POST') self._get_episode_watchlist() except (TraktException, AuthException, TokenExpiredException) as e: log.info( 'Unable to remove episodes from Trakt watchlist. Error: {error}', {'error': e.message})
def add_episode_watchlist(self): """Add episode to Tratk watchlist.""" if app.TRAKT_SYNC_WATCHLIST and app.USE_TRAKT: main_db_con = db.DBConnection() status = Quality.SNATCHED + Quality.SNATCHED_BEST + Quality.SNATCHED_PROPER + [ WANTED ] selection_status = [b'?' for _ in status] sql_selection = b'SELECT s.indexer, s.startyear, e.showid, s.show_name, e.season, e.episode ' \ b'FROM tv_episodes AS e, tv_shows AS s ' \ b'WHERE e.indexer = s.indexer AND s.indexer_id = e.showid AND s.paused = 0 ' \ b'AND e.status in ({0})'.format(b','.join(selection_status)) sql_result = main_db_con.select(sql_selection, status) episodes = [dict(i) for i in sql_result] if episodes: trakt_data = [] for cur_episode in episodes: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode[b'indexer']): continue if not self._check_list(indexer=cur_episode[b'indexer'], indexer_id=cur_episode[b'showid'], season=cur_episode[b'season'], episode=cur_episode[b'episode']): log.info( "Adding episode '{show}' {ep} to Trakt watchlist", { 'show': cur_episode[b'show_name'], 'ep': episode_num(cur_episode[b'season'], cur_episode[b'episode']) }) title = get_title_without_year( cur_episode[b'show_name'], cur_episode[b'startyear']) trakt_data.append( (cur_episode[b'showid'], cur_episode[b'indexer'], title, cur_episode[b'startyear'], cur_episode[b'season'], cur_episode[b'episode'])) if trakt_data: try: data = self.trakt_bulk_data_generate(trakt_data) self._request('sync/watchlist', data, method='POST') self._get_episode_watchlist() except (TraktException, AuthException, TokenExpiredException) as e: log.info( 'Unable to add episode to Trakt watchlist. Error: {error}', {'error': e.message})
def trakt_show_data_generate(data): """Build the JSON structure to send back to Trakt.""" show_list = [] for indexer, indexerid, title, year in data: show = {'title': title, 'year': year, 'ids': {}} show['ids'][get_trakt_indexer(indexer)] = indexerid show_list.append(show) post_data = {'shows': show_list} return post_data
def remove_show_trakt_library(self, show_obj): """Remove show from trakt library.""" if self.find_show(show_obj.indexerid, show_obj.indexer): # Check if TRAKT supports that indexer if not get_trakt_indexer(show_obj.indexer): return # URL parameters title = get_title_without_year(show_obj.name, show_obj.start_year) data = { 'shows': [ { 'title': title, 'year': show_obj.start_year, 'ids': {} } ] } data['shows'][0]['ids'][get_trakt_indexer(show_obj.indexer)] = show_obj.indexerid log.info("Removing '{show}' from Trakt library", {'show': show_obj.name}) # Remove all episodes from the Trakt collection for this show try: self.remove_episode_trakt_collection(filter_show=show_obj) except (TraktException, AuthException, TokenExpiredException) as error: log.info("Unable to remove all episodes from show '{show}' from Trakt library. Error: {error!r}", { 'show': show_obj.name, 'error': error }) try: self._request('sync/collection/remove', data, method='POST') except (TraktException, AuthException, TokenExpiredException) as error: log.info("Unable to remove show '{show}' from Trakt library. Error: {error!r}", { 'show': show_obj.name, 'error': error })
def remove_episode_trakt_collection(self, filter_show=None): """Remove episode from trakt collection. For episodes that no longer have a media file (location) :param filter_show: optional. Only remove episodes from trakt collection for given shows """ if app.TRAKT_SYNC_REMOVE and app.TRAKT_SYNC and app.USE_TRAKT: params = [] main_db_con = db.DBConnection() selection_status = ['?' for _ in Quality.DOWNLOADED + Quality.ARCHIVED] sql_selection = b'SELECT s.indexer, s.startyear, s.indexer_id, s.show_name,' \ b'e.season, e.episode, e.status ' \ b'FROM tv_episodes AS e, tv_shows AS s WHERE e.indexer = s.indexer AND ' \ b's.indexer_id = e.showid and e.location = "" ' \ b'AND e.status in ({0})'.format(','.join(selection_status)) if filter_show: sql_selection += b' AND s.indexer_id = ? AND e.indexer = ?' params = [filter_show.series_id, filter_show.indexer] sql_result = main_db_con.select(sql_selection, Quality.DOWNLOADED + Quality.ARCHIVED + params) episodes = [dict(e) for e in sql_result] if episodes: trakt_data = [] for cur_episode in episodes: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode[b'indexer']): continue if self._check_list(indexer=cur_episode[b'indexer'], indexer_id=cur_episode[b'indexer_id'], season=cur_episode[b'season'], episode=cur_episode[b'episode'], list_type='Collection'): log.info("Removing episode '{show}' {ep} from Trakt collection", { 'show': cur_episode[b'show_name'], 'ep': episode_num(cur_episode[b'season'], cur_episode[b'episode']) }) title = get_title_without_year(cur_episode[b'show_name'], cur_episode[b'startyear']) trakt_data.append((cur_episode[b'indexer_id'], cur_episode[b'indexer'], title, cur_episode[b'startyear'], cur_episode[b'season'], cur_episode[b'episode'])) if trakt_data: try: data = self.trakt_bulk_data_generate(trakt_data) self._request('sync/collection/remove', data, method='POST') self._get_show_collection() except (TraktException, AuthException, TokenExpiredException) as e: log.info('Unable to remove episodes from Trakt collection. Error: {error}', { 'error': e.message })
def remove_episode_trakt_collection(self, filter_show=None): """Remove episode from trakt collection. For episodes that no longer have a media file (location) :param filter_show: optional. Only remove episodes from trakt collection for given shows """ if app.TRAKT_SYNC_REMOVE and app.TRAKT_SYNC and app.USE_TRAKT: params = [] main_db_con = db.DBConnection() statuses = [DOWNLOADED, ARCHIVED] sql_selection = 'SELECT s.indexer, s.startyear, s.indexer_id, s.show_name,' \ 'e.season, e.episode, e.status ' \ 'FROM tv_episodes AS e, tv_shows AS s WHERE e.indexer = s.indexer AND ' \ 's.indexer_id = e.showid and e.location = "" ' \ 'AND e.status in ({0})'.format(','.join(['?'] * len(statuses))) if filter_show: sql_selection += ' AND s.indexer_id = ? AND e.indexer = ?' params = [filter_show.series_id, filter_show.indexer] sql_result = main_db_con.select(sql_selection, statuses + params) if sql_result: trakt_data = [] for cur_episode in sql_result: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode['indexer']): continue if self._check_list(indexer=cur_episode['indexer'], indexer_id=cur_episode['indexer_id'], season=cur_episode['season'], episode=cur_episode['episode'], list_type='Collection'): log.info("Removing episode '{show}' {ep} from Trakt collection", { 'show': cur_episode['show_name'], 'ep': episode_num(cur_episode['season'], cur_episode['episode']) }) title = get_title_without_year(cur_episode['show_name'], cur_episode['startyear']) trakt_data.append((cur_episode['indexer_id'], cur_episode['indexer'], title, cur_episode['startyear'], cur_episode['season'], cur_episode['episode'])) if trakt_data: try: data = self.trakt_bulk_data_generate(trakt_data) self._request('sync/collection/remove', data, method='POST') self._get_show_collection() except (TraktException, AuthException, TokenExpiredException) as error: log.info('Unable to remove episodes from Trakt collection. Error: {error!r}', { 'error': error })
def trakt_bulk_data_generate(trakt_data): """Build the JSON structure to send back to Trakt.""" unique_shows = {} unique_seasons = {} for indexer_id, indexer, show_name, start_year, season, episode in trakt_data: if indexer_id not in unique_shows: unique_shows[indexer_id] = { 'title': show_name, 'year': start_year, 'ids': {}, 'seasons': [] } unique_shows[indexer_id]['ids'][get_trakt_indexer( indexer)] = indexer_id unique_seasons[indexer_id] = [] # Get the unique seasons per Show for indexer_id, indexer, show_name, start_year, season, episode in trakt_data: if season not in unique_seasons[indexer_id]: unique_seasons[indexer_id].append(season) # build the query show_list = [] seasons_list = {} for searched_show in unique_shows: show = [] seasons_list[searched_show] = [] for searched_season in unique_seasons[searched_show]: episodes_list = [] for indexer_id, indexer, show_name, start_year, season, episode in trakt_data: if season == searched_season and indexer_id == searched_show: episodes_list.append({'number': episode}) show = unique_shows[searched_show] show['seasons'].append({ 'number': searched_season, 'episodes': episodes_list }) if show: show_list.append(show) post_data = {'shows': show_list} return post_data
def add_episode_trakt_collection(self): """Add all existing episodes to Trakt collections. For episodes that have a media file (location) """ if app.TRAKT_SYNC and app.USE_TRAKT: main_db_con = db.DBConnection() statuses = [DOWNLOADED, ARCHIVED] sql_selection = 'SELECT s.indexer, s.startyear, s.indexer_id, s.show_name, e.season, e.episode ' \ 'FROM tv_episodes AS e, tv_shows AS s ' \ 'WHERE e.indexer = s.indexer AND s.indexer_id = e.showid ' \ "AND e.status in ({0}) AND e.location <> ''".format(','.join(['?'] * len(statuses))) sql_result = main_db_con.select(sql_selection, statuses) if sql_result: trakt_data = [] for cur_episode in sql_result: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode['indexer']): continue if not self._check_list(indexer=cur_episode['indexer'], indexer_id=cur_episode['indexer_id'], season=cur_episode['season'], episode=cur_episode['episode'], list_type='Collection'): log.info("Adding episode '{show}' {ep} to Trakt collection", { 'show': cur_episode['show_name'], 'ep': episode_num(cur_episode['season'], cur_episode['episode']) }) title = get_title_without_year(cur_episode['show_name'], cur_episode['startyear']) trakt_data.append((cur_episode['indexer_id'], cur_episode['indexer'], title, cur_episode['startyear'], cur_episode['season'], cur_episode['episode'])) if trakt_data: try: data = self.trakt_bulk_data_generate(trakt_data) self._request('sync/collection', data, method='POST') self._get_show_collection() except (TraktException, AuthException, TokenExpiredException) as error: log.info('Unable to add episodes to Trakt collection. Error: {error!r}', {'error': error})
def remove_episode_watchlist(self): """Remove episode from Trakt watchlist.""" if app.TRAKT_SYNC_WATCHLIST and app.USE_TRAKT: main_db_con = db.DBConnection() statuses = [DOWNLOADED, ARCHIVED] sql_selection = 'SELECT s.indexer, s.startyear, e.showid, s.show_name, e.season, e.episode ' \ 'FROM tv_episodes AS e, tv_shows AS s ' \ 'WHERE e.indexer = s.indexer ' \ 'AND s.indexer_id = e.showid AND e.status in ({0})'.format(','.join(['?'] * len(statuses))) sql_result = main_db_con.select(sql_selection, statuses) if sql_result: trakt_data = [] for cur_episode in sql_result: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode['indexer']): continue if self._check_list(indexer=cur_episode['indexer'], indexer_id=cur_episode['showid'], season=cur_episode['season'], episode=cur_episode['episode']): log.info("Removing episode '{show}' {ep} from Trakt watchlist", { 'show': cur_episode['show_name'], 'ep': episode_num(cur_episode['season'], cur_episode['episode']) }) title = get_title_without_year(cur_episode['show_name'], cur_episode['startyear']) trakt_data.append((cur_episode['showid'], cur_episode['indexer'], title, cur_episode['startyear'], cur_episode['season'], cur_episode['episode'])) if trakt_data: try: data = self.trakt_bulk_data_generate(trakt_data) self._request('sync/watchlist/remove', data, method='POST') self._get_episode_watchlist() except (TraktException, AuthException, TokenExpiredException) as error: log.info('Unable to remove episodes from Trakt watchlist. Error: {error!r}', { 'error': error })
def trakt_bulk_data_generate(trakt_data): """Build the JSON structure to send back to Trakt.""" unique_shows = {} unique_seasons = {} for indexer_id, indexer, show_name, start_year, season, episode in trakt_data: if indexer_id not in unique_shows: unique_shows[indexer_id] = {'title': show_name, 'year': start_year, 'ids': {}, 'seasons': []} unique_shows[indexer_id]['ids'][get_trakt_indexer(indexer)] = indexer_id unique_seasons[indexer_id] = [] # Get the unique seasons per Show for indexer_id, indexer, show_name, start_year, season, episode in trakt_data: if season not in unique_seasons[indexer_id]: unique_seasons[indexer_id].append(season) # build the query show_list = [] seasons_list = {} for searched_show in unique_shows: show = [] seasons_list[searched_show] = [] for searched_season in unique_seasons[searched_show]: episodes_list = [] for indexer_id, indexer, show_name, start_year, season, episode in trakt_data: if season == searched_season and indexer_id == searched_show: episodes_list.append({'number': episode}) show = unique_shows[searched_show] show['seasons'].append({'number': searched_season, 'episodes': episodes_list}) if show: show_list.append(show) post_data = {'shows': show_list} return post_data
def remove_episode_trakt_collection(self, filter_show=None): """Remove episode from trakt collection. For episodes that no longer have a media file (location) :param filter_show: optional. Only remove episodes from trakt collection for given shows """ if not (app.TRAKT_SYNC_REMOVE and app.TRAKT_SYNC and app.USE_TRAKT): return params = [] main_db_con = db.DBConnection() statuses = [DOWNLOADED, ARCHIVED] sql_selection = 'SELECT s.indexer, s.startyear, s.indexer_id, s.show_name,' \ 'e.season, e.episode, e.status ' \ 'FROM tv_episodes AS e, tv_shows AS s WHERE e.indexer = s.indexer AND ' \ 's.indexer_id = e.showid and e.location = "" ' \ 'AND e.status in ({0})'.format(','.join(['?'] * len(statuses))) if filter_show: sql_selection += ' AND s.indexer_id = ? AND e.indexer = ?' params = [filter_show.series_id, filter_show.indexer] sql_result = main_db_con.select(sql_selection, statuses + params) if not sql_result: return episodes = [] shows = {} for cur_episode in sql_result: # Check if TRAKT supports that indexer if not get_trakt_indexer(cur_episode['indexer']): continue show_id = cur_episode['indexer'], cur_episode['indexer_id'] episode = cur_episode['season'], cur_episode['episode'] if show_id not in shows: shows[show_id] = [] shows[show_id].append(episode) media_object_shows = [] for show_id in shows: episodes = [] show_obj = Show.find_by_id(app.showList, show_id[0], show_id[1]) for season, episode in shows[show_id]: if not self._check_list( indexer=show_obj.indexer, indexer_id=show_obj.series_id, season=season, episode=episode, list_type='Collection' ): continue log.info("Removing episode '{show}' {ep} from Trakt collection", { 'show': show_obj.name, 'ep': episode_num(season, episode) }) episodes.append(show_obj.get_episode(season, episode)) media_object_shows.append(create_episode_structure(show_obj, episodes)) try: sync.remove_from_collection({'shows': media_object_shows}) self._get_show_collection() except TraktException as error: log.info('Unable to remove episodes from Trakt collection. Error: {error!r}', { 'error': error })
def update_library(ep_obj): """Send a request to trakt indicating that the given episode is part of our library. ep_obj: The Episode object to add to trakt """ # Check if TRAKT supports that indexer if not get_trakt_indexer(ep_obj.series.indexer): return # Create a trakt settings dict trakt_settings = { 'trakt_api_secret': app.TRAKT_API_SECRET, 'trakt_api_key': app.TRAKT_API_KEY, 'trakt_access_token': app.TRAKT_ACCESS_TOKEN, 'trakt_refresh_token': app.TRAKT_REFRESH_TOKEN } trakt_api = TraktApi(app.SSL_VERIFY, app.TRAKT_TIMEOUT, **trakt_settings) if app.USE_TRAKT: try: # URL parameters title = get_title_without_year(ep_obj.series.name, ep_obj.series.start_year) data = { 'shows': [{ 'title': title, 'year': ep_obj.series.start_year, 'ids': {}, }] } data['shows'][0]['ids'][get_trakt_indexer( ep_obj.series.indexer)] = ep_obj.series.indexerid if app.TRAKT_SYNC_WATCHLIST: if app.TRAKT_REMOVE_SERIESLIST: trakt_api.request('sync/watchlist/remove', data, method='POST') # Add Season and Episode + Related Episodes data['shows'][0]['seasons'] = [{ 'number': ep_obj.season, 'episodes': [] }] for relEp_Obj in [ep_obj] + ep_obj.related_episodes: data['shows'][0]['seasons'][0]['episodes'].append( {'number': relEp_Obj.episode}) if app.TRAKT_SYNC_WATCHLIST: if app.TRAKT_REMOVE_WATCHLIST: trakt_api.request('sync/watchlist/remove', data, method='POST') # update library trakt_api.request('sync/collection', data, method='POST') except (TokenExpiredException, TraktException, AuthException) as error: log.debug('Unable to update Trakt: {0}', error.message)
def update_watchlist(show_obj=None, s=None, e=None, data_show=None, data_episode=None, update='add'): """Send a request to trakt indicating that the given episode is part of our library. show_obj: The Series object to add to trakt s: season number e: episode number data_show: structured object of shows trakt type data_episode: structured object of episodes trakt type update: type o action add or remove """ # Check if TRAKT supports that indexer if not get_trakt_indexer(show_obj.indexer): return trakt_settings = { 'trakt_api_secret': app.TRAKT_API_SECRET, 'trakt_api_key': app.TRAKT_API_KEY, 'trakt_access_token': app.TRAKT_ACCESS_TOKEN, 'trakt_refresh_token': app.TRAKT_REFRESH_TOKEN } trakt_api = TraktApi(app.SSL_VERIFY, app.TRAKT_TIMEOUT, **trakt_settings) if app.USE_TRAKT: data = {} try: # URL parameters if show_obj is not None: title = get_title_without_year(show_obj.name, show_obj.start_year) data = { 'shows': [{ 'title': title, 'year': show_obj.start_year, 'ids': {}, }] } data['shows'][0]['ids'][get_trakt_indexer( show_obj.indexer)] = show_obj.indexerid elif data_show is not None: data.update(data_show) else: log.warning( "There's a coding problem contact developer. It's needed to be provided at" " least one of the two: data_show or show_obj", ) return False if data_episode is not None: data['shows'][0].update(data_episode) elif s is not None: # trakt URL parameters season = { 'season': [{ 'number': s, }] } if e is not None: # trakt URL parameters episode = {'episodes': [{'number': e}]} season['season'][0].update(episode) data['shows'][0].update(season) trakt_url = 'sync/watchlist' if update == 'remove': trakt_url += '/remove' trakt_api.request(trakt_url, data, method='POST') except (TokenExpiredException, TraktException, AuthException) as error: log.debug('Unable to update Trakt watchlist: {0}', error.message) return False return True