Exemple #1
0
    def massUpdate(self,
                   toUpdate=None,
                   toRefresh=None,
                   toRename=None,
                   toDelete=None,
                   toRemove=None,
                   toMetadata=None,
                   toSubtitle=None,
                   toImageUpdate=None):
        to_update = toUpdate.split('|') if toUpdate else []
        to_refresh = toRefresh.split('|') if toRefresh else []
        to_rename = toRename.split('|') if toRename else []
        to_subtitle = toSubtitle.split('|') if toSubtitle else []
        to_delete = toDelete.split('|') if toDelete else []
        to_remove = toRemove.split('|') if toRemove else []
        to_metadata = toMetadata.split('|') if toMetadata else []
        to_image_update = toImageUpdate.split('|') if toImageUpdate else []

        errors = []
        refreshes = []
        updates = []
        renames = []
        subtitles = []
        image_update = []

        for slug in set(to_update + to_refresh + to_rename + to_subtitle +
                        to_delete + to_remove + to_metadata + to_image_update):
            identifier = SeriesIdentifier.from_slug(slug)
            series_obj = Series.find_by_identifier(identifier)

            if not series_obj:
                continue

            if slug in to_delete + to_remove:
                app.show_queue_scheduler.action.removeShow(
                    series_obj, slug in to_delete)
                continue  # don't do anything else if it's being deleted or removed

            if slug in to_update:
                try:
                    app.show_queue_scheduler.action.updateShow(series_obj)
                    updates.append(series_obj.name)
                except CantUpdateShowException as msg:
                    errors.append(
                        'Unable to update show: {error}'.format(error=msg))

            elif slug in to_refresh:  # don't bother refreshing shows that were updated
                try:
                    app.show_queue_scheduler.action.refreshShow(series_obj)
                    refreshes.append(series_obj.name)
                except CantRefreshShowException as msg:
                    errors.append(
                        'Unable to refresh show {show.name}: {error}'.format(
                            show=series_obj, error=msg))

            if slug in to_rename:
                app.show_queue_scheduler.action.renameShowEpisodes(series_obj)
                renames.append(series_obj.name)

            if slug in to_subtitle:
                app.show_queue_scheduler.action.download_subtitles(series_obj)
                subtitles.append(series_obj.name)

            if slug in to_image_update:
                image_cache.replace_images(series_obj)

        if errors:
            ui.notifications.error('Errors encountered',
                                   '<br />\n'.join(errors))

        message = ''
        if updates:
            message += '\nUpdates: {0}'.format(len(updates))
        if refreshes:
            message += '\nRefreshes: {0}'.format(len(refreshes))
        if renames:
            message += '\nRenames: {0}'.format(len(renames))
        if subtitles:
            message += '\nSubtitles: {0}'.format(len(subtitles))
        if image_update:
            message += '\nImage updates: {0}'.format(len(image_update))

        if message:
            ui.notifications.message('Queued actions:', message)

        return self.redirect('/manage/')
Exemple #2
0
    def massUpdate(self, toUpdate=None, toRefresh=None, toRename=None, toDelete=None, toRemove=None, toMetadata=None,
                   toSubtitle=None, toImageUpdate=None):
        to_update = toUpdate.split('|') if toUpdate else []
        to_refresh = toRefresh.split('|') if toRefresh else []
        to_rename = toRename.split('|') if toRename else []
        to_subtitle = toSubtitle.split('|') if toSubtitle else []
        to_delete = toDelete.split('|') if toDelete else []
        to_remove = toRemove.split('|') if toRemove else []
        to_metadata = toMetadata.split('|') if toMetadata else []
        to_image_update = toImageUpdate.split('|') if toImageUpdate else []

        errors = []
        refreshes = []
        updates = []
        renames = []
        subtitles = []
        image_update = []

        for slug in set(to_update + to_refresh + to_rename + to_subtitle + to_delete + to_remove + to_metadata + to_image_update):
            identifier = SeriesIdentifier.from_slug(slug)
            series_obj = Series.find_by_identifier(identifier)

            if not series_obj:
                continue

            if slug in to_delete + to_remove:
                app.show_queue_scheduler.action.removeShow(series_obj, slug in to_delete)
                continue  # don't do anything else if it's being deleted or removed

            if slug in to_update:
                try:
                    app.show_queue_scheduler.action.updateShow(series_obj)
                    updates.append(series_obj.name)
                except CantUpdateShowException as msg:
                    errors.append('Unable to update show: {error}'.format(error=msg))

            elif slug in to_refresh:  # don't bother refreshing shows that were updated
                try:
                    app.show_queue_scheduler.action.refreshShow(series_obj)
                    refreshes.append(series_obj.name)
                except CantRefreshShowException as msg:
                    errors.append('Unable to refresh show {show.name}: {error}'.format
                                  (show=series_obj, error=msg))

            if slug in to_rename:
                app.show_queue_scheduler.action.renameShowEpisodes(series_obj)
                renames.append(series_obj.name)

            if slug in to_subtitle:
                app.show_queue_scheduler.action.download_subtitles(series_obj)
                subtitles.append(series_obj.name)

            if slug in to_image_update:
                image_cache.replace_images(series_obj)

        if errors:
            ui.notifications.error('Errors encountered',
                                   '<br />\n'.join(errors))

        message = ''
        if updates:
            message += '\nUpdates: {0}'.format(len(updates))
        if refreshes:
            message += '\nRefreshes: {0}'.format(len(refreshes))
        if renames:
            message += '\nRenames: {0}'.format(len(renames))
        if subtitles:
            message += '\nSubtitles: {0}'.format(len(subtitles))
        if image_update:
            message += '\nImage updates: {0}'.format(len(image_update))

        if message:
            ui.notifications.message('Queued actions:', message)

        return self.redirect('/manage/')
Exemple #3
0
    def run(self):

        ShowQueueItem.run(self)

        log.debug('{id}: Beginning update of {show}', {
            'id': self.show.series_id,
            'show': self.show.name
        })

        log.debug(
            '{id}: Retrieving show info from {indexer}', {
                'id': self.show.series_id,
                'indexer': indexerApi(self.show.indexer).name
            })
        try:
            # Let's make sure we refresh the indexer_api object attached to the show object.
            self.show.create_indexer()
            self.show.load_from_indexer()
        except IndexerError as error:
            log.warning(
                '{id}: Unable to contact {indexer}. Aborting: {error_msg}', {
                    'id': self.show.series_id,
                    'indexer': indexerApi(self.show.indexer).name,
                    'error_msg': error
                })
            return
        except IndexerAttributeNotFound as error:
            log.warning(
                '{id}: Data retrieved from {indexer} was incomplete. Aborting: {error_msg}',
                {
                    'id': self.show.series_id,
                    'indexer': indexerApi(self.show.indexer).name,
                    'error_msg': error
                })
            return
        except IndexerShowNotFoundInLanguage as error:
            log.warning(
                '{id}: Data retrieved from {indexer} was incomplete. The indexer does not provide'
                ' show information in the searched language {language}. Aborting: {error_msg}',
                {
                    'id': self.show.series_id,
                    'indexer': indexerApi(self.show.indexer).name,
                    'language': error.language,
                    'error_msg': error
                })
            ui.notifications.error(
                'Error changing language show!',
                'Unable to change language for show {show_name}'
                ' on {indexer} to language: {language}'.format(
                    show_name=self.show.name,
                    indexer=indexerApi(self.show.indexer).name,
                    language=error.language))
            return

        log.debug('{id}: Retrieving show info from IMDb',
                  {'id': self.show.series_id})
        try:
            self.show.load_imdb_info()
        except ImdbAPIError as error:
            log.info('{id}: Something wrong on IMDb api: {error_msg}', {
                'id': self.show.series_id,
                'error_msg': error
            })
        except RequestException as error:
            log.warning('{id}: Error loading IMDb info: {error_msg}', {
                'id': self.show.series_id,
                'error_msg': error
            })

        # have to save show before reading episodes from db
        try:
            log.debug('{id}: Saving new IMDb show info to database',
                      {'id': self.show.series_id})
            self.show.save_to_db()
        except Exception as error:
            log.warning(
                '{id}: Error saving new IMDb show info to database: {error_msg}',
                {
                    'id': self.show.series_id,
                    'error_msg': error
                })
            log.error(traceback.format_exc())

        # get episode list from DB
        try:
            episodes_from_db = self.show.load_episodes_from_db()
        except IndexerException as error:
            log.warning(
                '{id}: Unable to contact {indexer}. Aborting: {error_msg}', {
                    'id': self.show.series_id,
                    'indexer': indexerApi(self.show.indexer).name,
                    'error_msg': error
                })
            return

        # get episode list from the indexer
        try:
            episodes_from_indexer = self.show.load_episodes_from_indexer()
        except IndexerException as error:
            log.warning(
                '{id}: Unable to get info from {indexer}. The show info will not be refreshed.'
                ' Error: {error_msg}', {
                    'id': self.show.series_id,
                    'indexer': indexerApi(self.show.indexer).name,
                    'error_msg': error
                })
            episodes_from_indexer = None

        if episodes_from_indexer is None:
            log.warning(
                '{id}: No data returned from {indexer} during full show update.'
                ' Unable to update this show', {
                    'id': self.show.series_id,
                    'indexer': indexerApi(self.show.indexer).name
                })
        else:
            # for each ep we found on the Indexer delete it from the DB list
            for cur_season in episodes_from_indexer:
                for cur_episode in episodes_from_indexer[cur_season]:
                    if cur_season in episodes_from_db and cur_episode in episodes_from_db[
                            cur_season]:
                        del episodes_from_db[cur_season][cur_episode]

            # remaining episodes in the DB list are not on the indexer, just delete them from the DB
            for cur_season in episodes_from_db:
                for cur_episode in episodes_from_db[cur_season]:
                    log.debug(
                        '{id}: Permanently deleting episode {show} {ep} from the database',
                        {
                            'id': self.show.series_id,
                            'show': self.show.name,
                            'ep': episode_num(cur_season, cur_episode)
                        })
                    # Create the ep object only because Im going to delete it
                    ep_obj = self.show.get_episode(cur_season, cur_episode)
                    try:
                        ep_obj.delete_episode()
                    except EpisodeDeletedException:
                        log.debug(
                            '{id}: Episode {show} {ep} successfully deleted from the database',
                            {
                                'id': self.show.series_id,
                                'show': self.show.name,
                                'ep': episode_num(cur_season, cur_episode)
                            })

        # Save only after all changes were applied
        try:
            log.debug('{id}: Saving all updated show info to database',
                      {'id': self.show.series_id})
            self.show.save_to_db()
        except Exception as error:
            log.warning(
                '{id}: Error saving all updated show info to database: {error_msg}',
                {
                    'id': self.show.series_id,
                    'error_msg': error
                })
            log.error(traceback.format_exc())

        # Replace the images in cache
        log.info('{id}: Replacing images for show {show}', {
            'id': self.show.series_id,
            'show': self.show.name
        })
        replace_images(self.show)

        log.debug('{id}: Finished update of {show}', {
            'id': self.show.series_id,
            'show': self.show.name
        })

        # Refresh show needs to be forced since current execution locks the queue
        app.show_queue_scheduler.action.refreshShow(self.show, True)
        self.finish()
    def post(self):
        """Perform a mass update action."""
        data = json_decode(self.request.body)
        update = data.get('update', [])
        rescan = data.get('rescan', [])
        rename = data.get('rename', [])
        subtitle = data.get('subtitle', [])
        delete = data.get('delete', [])
        remove = data.get('remove', [])
        image = data.get('image', [])

        result = {
            'shows': defaultdict(list),
            'totals': {
                'update': 0,
                'rescan': 0,
                'rename': 0,
                'subtitle': 0,
                'delete': 0,
                'remove': 0,
                'image': 0
            }
        }

        for slug in set(update + rescan + rename + subtitle + delete + remove + image):
            identifier = SeriesIdentifier.from_slug(slug)
            series_obj = Series.find_by_identifier(identifier)

            if not series_obj:
                result['shows'][slug].append('Unable to locate show: {show}'.format(show=slug))
                continue

            if slug in delete + remove:
                app.show_queue_scheduler.action.removeShow(series_obj, slug in delete)
                if slug in delete:
                    result['totals']['delete'] += 1
                if slug in remove:
                    result['totals']['remove'] += 1
                continue  # don't do anything else if it's being deleted or removed

            if slug in update:
                try:
                    app.show_queue_scheduler.action.updateShow(series_obj)
                    result['totals']['update'] += 1
                except CantUpdateShowException as msg:
                    result['shows'][slug].append('Unable to update show: {error}'.format(error=msg))

            elif slug in rescan:  # don't bother refreshing shows that were updated
                try:
                    app.show_queue_scheduler.action.refreshShow(series_obj)
                    result['totals']['rescan'] += 1
                except CantRefreshShowException as msg:
                    result['shows'][slug].append(
                        'Unable to refresh show {show.name}: {error}'.format(show=series_obj, error=msg)
                    )

            if slug in rename:
                app.show_queue_scheduler.action.renameShowEpisodes(series_obj)
                result['totals']['rename'] += 1

            if slug in subtitle:
                app.show_queue_scheduler.action.download_subtitles(series_obj)
                result['totals']['subtitle'] += 1

            if slug in image:
                image_cache.replace_images(series_obj)
                result['totals']['image'] += 1

        if result['shows']:
            ui.notifications.error('Errors encountered', '<br />\n'.join(chain(*result['shows'].values())))

        return self._created(data=result)