示例#1
0
    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.")
示例#2
0
    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)
示例#3
0
    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.')
示例#4
0
    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
示例#5
0
    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)
示例#6
0
 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.")
示例#7
0
    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.")
示例#8
0
    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)
示例#9
0
    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
示例#10
0
    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
示例#11
0
    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
示例#12
0
    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.')
示例#13
0
    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)
示例#14
0
    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)
示例#15
0
    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)
示例#16
0
    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)
示例#17
0
    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