def finish(self): if self.current.kwargs.get('section'): # Collection cleaning disabled for individual syncs return # Increment progress steps self.current.progress.group(Movies, 'missing:movies').add(len(self.current.pending['movies'].keys)) # Iterate over movies for pk in list(self.current.pending['movies'].keys): # Increment one step self.current.progress.group(Movies, 'missing:movies').step() # Iterate over data handlers triggered = False for data in self.get_data(SyncMedia.Movies): if data not in [SyncData.Collection]: continue # Retrieve movie t_movie = self.trakt[(SyncMedia.Movies, data)].get(pk) if not t_movie: continue log.debug('Found movie missing from plex: %r [data: %r]', pk, SyncData.title(data)) # Trigger handler self.execute_handlers( self.mode, SyncMedia.Movies, data, key=None, guid=Guid.construct(*pk, matched=True), p_item=None, t_item=t_movie ) # Mark triggered triggered = True # Check if action was triggered if not triggered: continue # Remove movie from `pending` set self.current.pending['movies'].keys.remove(pk) # Stop progress group self.current.progress.group(Movies, 'missing:movies').stop() # Report pending movies (no actions triggered) self.log_pending( log, 'Unable to find %d movie(s) in Plex, list has been saved to: %s', self.current.account, 'movies', self.current.pending['movies'].keys )
def process_missing_shows(self): if self.current.kwargs.get('section'): # Collection cleaning disabled for individual syncs return # Increment progress steps self.current.progress.group(Shows, 'missing:shows').add(len(self.p_shows_pending)) # Iterate over trakt shows (that aren't in plex) for pk in list(self.p_shows_pending): # Increment one step self.current.progress.group(Shows, 'missing:shows').step() # Iterate over data handlers triggered = False for data in self.get_data(SyncMedia.Shows): if data not in [SyncData.Collection]: continue # Retrieve show t_show = self.trakt[(SyncMedia.Shows, data)].get(pk) if not t_show: continue log.debug('Found show missing from plex: %r [data: %r]', pk, SyncData.title(data)) # Trigger handler self.execute_handlers( SyncMedia.Shows, data, key=None, guid=Guid.construct(*pk), p_item=None, t_item=t_show ) # Mark triggered triggered = True # Check if action was triggered if not triggered: continue # Remove movie from `pending` set self.p_shows_pending.remove(pk) # Stop progress group self.current.progress.group(Shows, 'missing:shows').stop() self.log_pending('Unable to find %d show(s) in Plex\n%s', self.p_shows_pending)
def process_missing_shows(self): if self.current.kwargs.get('section'): # Collection cleaning disabled for individual syncs return # Increment progress steps self.current.progress.group(Shows, 'missing:shows').add( len(self.p_shows_pending)) # Iterate over trakt shows (that aren't in plex) for pk in list(self.p_shows_pending): # Increment one step self.current.progress.group(Shows, 'missing:shows').step() # Iterate over data handlers triggered = False for data in self.get_data(SyncMedia.Shows): if data not in [SyncData.Collection]: continue # Retrieve show t_show = self.trakt[(SyncMedia.Shows, data)].get(pk) if not t_show: continue log.debug('Found show missing from plex: %r [data: %r]', pk, SyncData.title(data)) # Trigger handler self.execute_handlers(SyncMedia.Shows, data, key=None, guid=Guid.construct(*pk), p_item=None, t_item=t_show) # Mark triggered triggered = True # Check if action was triggered if not triggered: continue # Remove movie from `pending` set self.p_shows_pending.remove(pk) # Stop progress group self.current.progress.group(Shows, 'missing:shows').stop() self.log_pending('Unable to find %d show(s) in Plex\n%s', self.p_shows_pending)
def parse(cls, guid, episode=None): media = ( GuidMatch.Media.Episode if episode else GuidMatch.Media.Movie ) # Ensure guid is valid if not guid or not guid.valid: return GuidMatch( media, guid, invalid=True ) # Process guid episode identifier overrides if episode and len(episode) == 2: season_num, episode_num = episode if guid.season is not None: episode = guid.season, episode_num # Process natively supported guid services if guid.service in GUID_SERVICES: episodes = None if episode and len(episode) == 2: episodes = [episode] return GuidMatch( media, guid, episodes=episodes, supported=True, found=True ) # Process episode if episode: return cls.parse_episode(guid, episode) # Process shows + movies supported, (service, key) = ModuleManager['mapper'].id( guid.service, guid.id, resolve_mappings=False ) # Validate match if not supported: return GuidMatch(media, guid) if not service or not key: return GuidMatch(media, guid, supported=True) # Validate identifier if type(key) is list: log.info('[%s/%s] - List keys are not supported', guid.service, guid.id) return GuidMatch(media, guid, supported=True) if type(key) not in [int, str]: log.info('[%s/%s] - Unsupported key: %r', guid.service, guid.id, key) return GuidMatch(media, guid, supported=True) log.debug('[%s/%s] - Mapped to: %s/%s', guid.service, guid.id, service, key) # Return movie/show match return GuidMatch( media, Guid.construct(service, key, matched=True), supported=True, found=True )
def finish_episodes(self): if self.current.kwargs.get('section'): # Collection cleaning disabled for individual syncs return # Increment progress steps self.current.progress.group(Shows, 'missing:episodes').add( len(self.current.pending['episodes'].keys)) # Iterate over trakt episodes (that aren't in plex) for pk, episodes in [ (p, list(e)) for (p, e) in self.current.pending['episodes'].keys.items() ]: # Increment one step self.current.progress.group(Shows, 'missing:episodes').step() # Iterate over trakt episodes (that aren't in plex) for identifier in episodes: # Iterate over data handlers season_num, episode_num = identifier triggered = False for data in self.get_data(SyncMedia.Episodes): if data not in [SyncData.Collection]: continue # Retrieve episode t_show, t_season, t_episode = self.t_objects( self.trakt[(SyncMedia.Episodes, data)], pk, season_num, episode_num) if not t_episode: continue log.debug( 'Found episode missing from plex: %r - %r [data: %r]', pk, identifier, SyncData.title(data)) # Trigger handler self.execute_handlers(self.mode, SyncMedia.Episodes, data, key=None, identifier=identifier, guid=Guid.construct(*pk, matched=True), p_show=None, p_item=None, t_show=t_show, t_item=t_episode) # Mark triggered triggered = True # Check if action was triggered if not triggered: continue # Remove movie from `pending` set self.current.pending['episodes'].keys[pk].remove(identifier) # Stop progress group self.current.progress.group(Shows, 'missing:episodes').stop() self.log_pending( log, 'Unable to find %d episode(s) in Plex, list has been saved to: %s', self.current.account, 'episodes', self.current.pending['episodes'].keys)
def process_missing_episodes(self): if self.current.kwargs.get('section'): # Collection cleaning disabled for individual syncs return # Increment progress steps self.current.progress.group(Shows, 'missing:episodes').add(len(self.p_episodes_pending)) # Iterate over trakt episodes (that aren't in plex) for pk, episodes in [(p, list(e)) for (p, e) in self.p_episodes_pending.items()]: # Increment one step self.current.progress.group(Shows, 'missing:episodes').step() # Iterate over trakt episodes (that aren't in plex) for identifier in episodes: # Iterate over data handlers season_num, episode_num = identifier triggered = False for data in self.get_data(SyncMedia.Episodes): if data not in [SyncData.Collection]: continue # Retrieve episode t_show, t_season, t_episode = self.t_objects( self.trakt[(SyncMedia.Episodes, data)], pk, season_num, episode_num ) if not t_episode: continue log.debug('Found episode missing from plex: %r - %r [data: %r]', pk, identifier, SyncData.title(data)) # Trigger handler self.execute_handlers( SyncMedia.Episodes, data, key=None, identifier=identifier, guid=Guid.construct(*pk), p_show=None, p_item=None, t_show=t_show, t_item=t_episode ) # Mark triggered triggered = True # Check if action was triggered if not triggered: continue # Remove movie from `pending` set self.p_episodes_pending[pk].remove(identifier) # Stop progress group self.current.progress.group(Shows, 'missing:episodes').stop() self.log_pending('Unable to find %d episode(s) in Plex\n%s', self.p_episodes_pending)
def parse(cls, guid, episode=None): media = (GuidMatch.Media.Episode if episode else GuidMatch.Media.Movie) # Ensure guid is valid if not guid or not guid.valid: return GuidMatch(media, guid, invalid=True) # Process guid episode identifier overrides if episode and len(episode) == 2: season_num, episode_num = episode if guid.season is not None: episode = guid.season, episode_num # Process natively supported guid services if guid.service in GUID_SERVICES: episodes = None if episode and len(episode) == 2: episodes = [episode] return GuidMatch(media, guid, episodes=episodes, supported=True, found=True) # Process episode if episode: return cls.parse_episode(guid, episode) # Process shows + movies supported, (service, key) = ModuleManager['mapper'].id(guid.service, guid.id, resolve_mappings=False) # Validate match if not supported: return GuidMatch(media, guid) if not service or not key: return GuidMatch(media, guid, supported=True) # Validate identifier if type(key) is list: log.info('[%s/%s] - List keys are not supported', guid.service, guid.id) return GuidMatch(media, guid, supported=True) if type(key) not in [int, str]: log.info('[%s/%s] - Unsupported key: %r', guid.service, guid.id, key) return GuidMatch(media, guid, supported=True) log.debug('[%s/%s] - Mapped to: %s/%s', guid.service, guid.id, service, key) # Return movie/show match return GuidMatch(media, Guid.construct(service, key, matched=True), supported=True, found=True)
class GuidParser(object): @classmethod def parse(cls, guid, episode=None): media = (GuidMatch.Media.Episode if episode else GuidMatch.Media.Movie) # Ensure guid is valid if not guid or not guid.valid: return GuidMatch(media, guid, invalid=True) # Process guid episode identifier overrides if episode and len(episode) == 2: season_num, episode_num = episode if guid.season is not None: episode = guid.season, episode_num # Process natively supported guid services if guid.service in GUID_SERVICES: episodes = None if episode and len(episode) == 2: episodes = [episode] return GuidMatch(media, guid, episodes=episodes, supported=True, found=True) # Process episode if episode: return cls.parse_episode(guid, episode) # Process shows + movies supported, (service, key) = ModuleManager['mapper'].id(guid.service, guid.id, resolve_mappings=False) # Validate match if not supported: return GuidMatch(media, guid) if not service or not key: return GuidMatch(media, guid, supported=True) # Validate identifier if type(key) is list: log.info('[%s/%s] - List keys are not supported', guid.service, guid.id) return GuidMatch(media, guid, supported=True) if type(key) not in [int, str]: log.info('[%s/%s] - Unsupported key: %r', guid.service, guid.id, key) return GuidMatch(media, guid, supported=True) log.debug('[%s/%s] - Mapped to: %s/%s', guid.service, guid.id, service, key) # Return movie/show match return GuidMatch(media, Guid.construct(service, key, matched=True), supported=True, found=True) @classmethod def parse_episode(cls, guid, (season_num, episode_num)): episodes = [(season_num, episode_num)] # Map episode to a supported service (via OEM) supported, match = ModuleManager['mapper'].map_episode( guid, season_num, episode_num, resolve_mappings=False) # Validate match if not supported: return GuidMatch(GuidMatch.Media.Episode, guid, episodes=episodes) if not match or not match.identifiers: log.debug('Unable to find mapping for %r S%02dE%02d', guid, season_num, episode_num) return GuidMatch(GuidMatch.Media.Episode, guid, episodes=episodes, supported=True) # Retrieve identifier service = match.identifiers.keys()[0] key = match.identifiers[service] if type(key) is list: log.info('[%s/%s] - List keys are not supported', guid.service, guid.id) return GuidMatch(GuidMatch.Media.Episode, guid, episodes=episodes, supported=True) # Cast `key` numbers to integers key = try_convert(key, int, key) # Validate show identifier if type(key) not in [int, str]: log.info('[%s/%s] - Unsupported key: %r', guid.service, guid.id, key) return GuidMatch(GuidMatch.Media.Episode, guid, episodes=episodes, supported=True) # Process episode matches if isinstance(match, EpisodeMatch): # Ensure match doesn't include an absolute number if match.absolute_num is not None: log.info( '[%s/%s] - Episode mappings with absolute numbers are not supported', guid.service, guid.id) return GuidMatch(GuidMatch.Media.Episode, guid, episodes=episodes, supported=True) # Update `episodes` list if match.mappings: # Use match mappings episodes = [] for mapping in match.mappings: log.debug('[%s/%s] (S%02dE%02d) - Mapped to: %r', guid.service, guid.id, season_num, episode_num, mapping) episodes.append((int(mapping.season), int(mapping.number))) else: # Use match identifier log.debug('[%s/%s] (S%02dE%02d) - Mapped to: %r', guid.service, guid.id, season_num, episode_num, match) episodes = [(int(match.season_num), int(match.episode_num))] # Return episode match return GuidMatch(GuidMatch.Media.Episode, Guid.construct(service, key, matched=True), episodes=episodes, supported=True, found=True) # Process movie matches if isinstance(match, MovieMatch): log.debug('[%s/%s] (S%02dE%02d) - Mapped to: %r', guid.service, guid.id, season_num, episode_num, match) # Return movie match return GuidMatch(GuidMatch.Media.Movie, Guid.construct(service, key, matched=True), supported=True, found=True) # Unknown value for `match` returned log.warn('Unknown match returned: %r', match) return GuidMatch(GuidMatch.Media.Episode, guid, episodes=episodes, supported=True)