def get_show_info(self, pattern): """ Returns the complete info for a show It asks the data handler for the full details of a show, and returns it as a show dictionary. pattern: The show ID as a number or the full show title. """ showdict = self.data_handler.get() try: # ID lookup showid = int(pattern) try: return showdict[showid] except KeyError: raise utils.EngineError("Show not found.") except ValueError: # Do title lookup, slower for k, show in showdict.iteritems(): if show['title'] == pattern: return show raise utils.EngineError("Show not found.")
def set_episode(self, showid, newep): """ Updates the progress of the specified **showid** to **newep** and queues the list update for the next sync. """ # Check if operation is supported by the API if not self.mediainfo.get('can_update'): raise utils.EngineError('Operation not supported by API.') # Check for the episode number try: newep = int(newep) except ValueError: raise utils.EngineError('Episode must be numeric.') # Get the show info show = self.get_show_info(showid) # More checks if (show['total'] and newep > show['total']) or newep < 0: raise utils.EngineError('Episode out of limits.') if show['my_progress'] == newep: raise utils.EngineError("Show already at episode %d" % newep) # Change episode self.msg.info( self.name, "Updating show %s to episode %d..." % (show['title'], newep)) self.data_handler.queue_update(show, 'my_progress', newep) # Emit signal self._emit_signal('episode_changed', show) # Change status if required if self.config['auto_status_change'] and self.mediainfo.get( 'can_status'): try: if newep == show['total'] and self.mediainfo.get( 'status_finish'): if (not self.config['auto_status_change_if_scored'] or not self.mediainfo.get('can_score') or show['my_score']): # Change to finished status self.set_status(show['id'], self.mediainfo['status_finish']) else: self.msg.warn( self.name, "Updated episode but status won't be changed until a score is set." ) elif newep == 1 and self.mediainfo.get('status_start'): # Change to watching status self.set_status(show['id'], self.mediainfo['status_start']) except utils.EngineError, e: # Only warn about engine errors since status change here is not crtical self.msg.warn( self.name, 'Updated episode but status wasn\'t changed: %s' % e)
def play_episode(self, show, playep=0): """ Searches the hard disk for an episode and plays the episode Does a local search in the hard disk (in the folder specified by the config file) for the specified episode for the specified show. show: Show dictionary playep: Episode to play. Optional. If none specified, the next episode will be played. """ # Check if operation is supported by the API if not self.mediainfo.get('can_play'): raise utils.EngineError('Operation not supported by API.') try: playep = int(playep) except ValueError: raise utils.EngineError('Episode must be numeric.') if show: playing_next = False if not playep: playep = show['my_progress'] + 1 playing_next = True if show['total'] and playep > show['total']: raise utils.EngineError('Episode beyond limits.') self.msg.info(self.name, "Searching for %s %s..." % (show['title'], playep)) if self.data_handler.altname_get(show['id']): titles = [self.data_handler.altname_get(show['id'])] else: titles = [show['title']] titles.extend(show['aliases']) filename = self._search_video(titles, playep) if filename: self.msg.info(self.name, 'Found. Starting player...') self.playing = True try: subprocess.call([self.config['player'], filename]) except OSError: raise utils.EngineError( 'Player not found, check your config.json') self.playing = False return playep else: raise utils.EngineError('Episode file not found.')
def set_episode(self, show_pattern, newep): """ Updates the progress for a show It asks the data handler to update the progress of the specified show to a specified number. show_pattern: ID or full title of the show newep: The progress number to update the show to """ # Check if operation is supported by the API if not self.mediainfo.get('can_update'): raise utils.EngineError('Operation not supported by API.') # Check for the episode number try: newep = int(newep) except ValueError: raise utils.EngineError('Episode must be numeric.') # Get the show info show = self.get_show_info(show_pattern) # More checks if show['total'] and newep > show['total']: raise utils.EngineError('Episode out of limits.') if show['my_progress'] == newep: raise utils.EngineError("Show already at episode %d" % newep) # Change episode self.msg.info( self.name, "Updating show %s to episode %d..." % (show['title'], newep)) self.data_handler.queue_update(show, 'my_progress', newep) # Change status if required if self.config['auto_status_change']: if newep == 1 and self.mediainfo.get('status_start'): self.data_handler.queue_update(show, 'my_status', self.mediainfo['status_start']) self._emit_signal('status_changed', show) elif newep == show['total'] and self.mediainfo.get( 'status_finish'): self.data_handler.queue_update(show, 'my_status', self.mediainfo['status_finish']) self._emit_signal('status_changed', show) # Emit signal self._emit_signal('episode_changed', show) return show
def set_score(self, showid, newscore): """ Updates the score of the specified **showid** to **newscore** and queues the list update for the next sync. """ # Check if operation is supported by the API if not self.mediainfo.get('can_score'): raise utils.EngineError('Operation not supported by API.') # Check for the correctness of the score if (Decimal(str(newscore)) % Decimal(str(self.mediainfo['score_step']))) != 0: raise utils.EngineError('Invalid score.') # Convert to proper type if isinstance(self.mediainfo['score_step'], int): newscore = int(newscore) else: newscore = float(newscore) # Get the show and update it show = self.get_show_info(showid) # More checks if newscore > self.mediainfo['score_max']: raise utils.EngineError('Score out of limits.') if show['my_score'] == newscore: raise utils.EngineError("Score already at %s" % newscore) # Change score self.msg.info( self.name, "Updating show %s to score %s..." % (show['title'], newscore)) self.data_handler.queue_update(show, 'my_score', newscore) # Emit signal self._emit_signal('score_changed', show) # Change status if required if (show['total'] and show['my_progress'] == show['total'] and show['my_score'] and self.mediainfo.get('can_status') and self.config['auto_status_change'] and self.config['auto_status_change_if_scored'] and self.mediainfo.get('status_finish')): try: self.set_status(show['id'], self.mediainfo['status_finish']) except utils.EngineError, e: # Only warn about engine errors since status change here is not crtical self.msg.warn( self.name, 'Updated episode but status wasn\'t changed: %s' % e)
def get_show_info_title(self, pattern): showdict = self.data_handler.get() # Do title lookup, slower for k, show in showdict.iteritems(): if show['title'] == pattern: return show raise utils.EngineError("Show not found.")
def get_show_info(self, showid): """ Returns the show dictionary for the specified **showid**. """ showdict = self.data_handler.get() try: return showdict[showid] except KeyError: raise utils.EngineError("Show not found.")
def set_dates(self, showid, start_date=None, finish_date=None): """ Updates the start date and finish date of a show. If any of the two are None, it won't be changed. """ if not self.mediainfo.get('can_date'): raise utils.EngineError('Operation not supported by API.') show = self.get_show_info(showid) # Change the start date if required if start_date: if not isinstance(start_date, datetime.date): raise utils.EngineError('start_date must be a Date object.') self.data_handler.queue_update(show, 'my_start_date', start_date) if finish_date: if not isinstance(finish_date, datetime.date): raise utils.EngineError('finish_date must be a Date object.') self.data_handler.queue_update(show, 'my_finish_date', finish_date)
def set_score(self, show_pattern, newscore): """ Updates the score for a show It asks the data handler to update the score of the specified show to a specified number. show_pattern: ID or full title of the show newscore: The score number to update the show to """ # Check if operation is supported by the API if not self.mediainfo.get('can_score'): raise utils.EngineError('Operation not supported by API.') # Check for the correctness of the score try: newscore = int(newscore) except ValueError: raise utils.EngineError('Score must be numeric.') # Get the show and update it show = self.get_show_info(show_pattern) # More checks if newscore > 10: raise utils.EngineError('Score out of limits.') if show['my_score'] == newscore: raise utils.EngineError("Score already at %d" % newscore) # Change score self.msg.info( self.name, "Updating show %s to score %d..." % (show['title'], newscore)) self.data_handler.queue_update(show, 'my_score', newscore) # Emit signal self._emit_signal('score_changed', show) return show
def set_status(self, show_pattern, newstatus): """ Updates the status for a show It asks the data handler to update the status of the specified show to a specified number. show_pattern: ID or full title of the show newstatus: The status number to update the show to """ # Check if operation is supported by the API if not self.mediainfo.get('can_status'): raise utils.EngineError('Operation not supported by API.') # Check for the correctness of the score try: newstatus = int(newstatus) except ValueError: raise utils.EngineError('Status must be numeric.') # Get the show and update it _statuses = self.mediainfo['statuses_dict'] show = self.get_show_info(show_pattern) # More checks if show['my_status'] == newstatus: raise utils.EngineError("Show already in %s." % _statuses[newstatus]) # Change score self.msg.info( self.name, "Updating show %s status to %s..." % (show['title'], _statuses[newstatus])) self.data_handler.queue_update(show, 'my_status', newstatus) # Emit signal self._emit_signal('status_changed', show) return show
def set_status(self, showid, newstatus): """ Updates the score of the specified **showid** to **newstatus** (number) and queues the list update for the next sync. """ # Check if operation is supported by the API if not self.mediainfo.get('can_status'): raise utils.EngineError('Operation not supported by API.') try: newstatus = int(newstatus) except ValueError: pass # It's not necessary for it to be an int # Check if the status is valid _statuses = self.mediainfo['statuses_dict'] if newstatus not in _statuses.keys(): raise utils.EngineError('Invalid status.') # Get the show and update it show = self.get_show_info(showid) # More checks if show['my_status'] == newstatus: raise utils.EngineError("Show already in %s." % _statuses[newstatus]) # Change status old_status = show['my_status'] self.msg.info( self.name, "Updating show %s status to %s..." % (show['title'], _statuses[newstatus])) self.data_handler.queue_update(show, 'my_status', newstatus) # Emit signal self._emit_signal('status_changed', show, old_status) return show
def play_episode(self, show, playep=0): """ Does a local search in the hard disk (in the folder specified by the config file) for the specified episode (**playep**) for the specified **show**. If no **playep** is specified, the next episode of the show will be played. """ # Check if operation is supported by the API if not self.mediainfo.get('can_play'): raise utils.EngineError( 'Operation not supported by current site or mediatype.') if not self.config['searchdir']: raise utils.EngineError('Media directory is not set.') if not utils.dir_exists(self.config['searchdir']): raise utils.EngineError('The set media directory doesn\'t exist.') try: playep = int(playep) except ValueError: raise utils.EngineError('Episode must be numeric.') if show: playing_next = False if not playep: playep = show['my_progress'] + 1 playing_next = True if show['total'] and playep > show['total']: raise utils.EngineError('Episode beyond limits.') self.msg.info(self.name, "Searching for %s %s..." % (show['title'], playep)) titles = self.data_handler.get_show_titles(show) filename, endep = self._search_video(titles, playep) if filename: self.msg.info(self.name, 'Found. Starting player...') arg_list = shlex.split(self.config['player']) arg_list.append(filename) try: with open(os.devnull, 'wb') as DEVNULL: subprocess.Popen(arg_list, stdout=DEVNULL, stderr=DEVNULL) except OSError: raise utils.EngineError( 'Player not found, check your config.json') return endep else: raise utils.EngineError('Episode file not found.')
def delete_show(self, show): """ Deletes **show** completely from the list and queues the list update for the next sync. """ if not self.mediainfo.get('can_delete'): raise utils.EngineError('Operation not supported by API.') # Add in data handler self.data_handler.queue_delete(show) # Update the tracker with the new information self._update_tracker() # Emit signal self._emit_signal('show_deleted', show)
def add_show(self, show, status=None): """ Adds **show** to the list and queues the list update for the next sync. """ # Check if operation is supported by the API if not self.mediainfo.get('can_add'): raise utils.EngineError('Operation not supported by API.') # Set to the requested status if status: if status not in self.mediainfo['statuses']: raise utils.EngineError('Invalid status.') show['my_status'] = status # Add in data handler self.data_handler.queue_add(show) # Update the tracker with the new information self._update_tracker() # Emit signal self._emit_signal('show_added', show)
def delete_show(self, show): """ Deletes a show completely from the list show: Show dictionary """ if not self.mediainfo.get('can_delete'): raise utils.EngineError('Operation not supported by API.') # Add in data handler self.data_handler.queue_delete(show) # Emit signal self._emit_signal('show_deleted', show)
def add_show(self, show): """ Adds a show to the list It adds a show to the list and queues the list update for the next sync. show: Full show dictionary """ # Check if operation is supported by the API if not self.mediainfo.get('can_add'): raise utils.EngineError('Operation not supported by API.') # Add in data handler self.data_handler.queue_add(show) # Emit signal self._emit_signal('show_added', show)
def scan_library(self, my_status=None, ignorecache=False): # Check if operation is supported by the API if not self.mediainfo.get('can_play'): raise utils.EngineError( 'Operation not supported by current site or mediatype.') if not self.config['searchdir']: raise utils.EngineError('Media directory is not set.') if not utils.dir_exists(self.config['searchdir']): raise utils.EngineError('The set media directory doesn\'t exist.') t = time.time() library = {} library_cache = self.data_handler.library_cache_get() if not my_status: my_status = self.mediainfo['status_start'] self.msg.info(self.name, "Scanning local library...") tracker_list = self._get_tracker_list(my_status) # Do a full listing of the media directory for fullpath, filename in utils.regex_find_videos( 'mkv|mp4|avi', self.config['searchdir']): show_id = None if not ignorecache and filename in library_cache.keys(): # If the filename was already seen before # use the cached information, if there's no information (None) # then it means it doesn't correspond to any show in the list # and can be safely skipped. if library_cache[filename]: show_id = library_cache[filename][0] show_ep = library_cache[filename][1] else: continue else: # If the filename has not been seen, extract # the information from the filename and do a fuzzy search # on the user's list. Cache the information. # If it fails, cache it as None. aie = extras.AnimeInfoExtractor.AnimeInfoExtractor(filename) (show_title, show_ep) = (aie.getName(), aie.getEpisode()) if show_title: show = utils.guess_show(show_title, tracker_list) if show: show_id = show['id'] library_cache[filename] = (show['id'], show_ep) else: library_cache[filename] = None else: library_cache[filename] = None # After we got our information, add it to our library if show_id: if show_id not in library.keys(): library[show_id] = {} library[show_id][show_ep] = fullpath self.msg.debug(self.name, "Time: %s" % (time.time() - t)) self.data_handler.library_save(library) self.data_handler.library_cache_save(library_cache) return library