示例#1
0
    def post(self, series_slug=None, path_param=None):
        """Add a new series."""
        if series_slug is not None:
            return self._bad_request('Series slug should not be specified')

        data = json_decode(self.request.body)
        if not data or 'id' not in data:
            return self._bad_request('Invalid series data')

        ids = {k: v for k, v in viewitems(data['id']) if k != 'imdb'}
        if len(ids) != 1:
            return self._bad_request(
                'Only 1 indexer identifier should be specified')

        identifier = SeriesIdentifier.from_slug('{slug}{id}'.format(
            slug=list(ids)[0], id=list(itervalues(ids))[0]))
        if not identifier:
            return self._bad_request('Invalid series identifier')

        series = Series.find_by_identifier(identifier)
        if series:
            return self._conflict('Series already exist added')

        series = Series.from_identifier(identifier)
        if not Series.save_series(series):
            return self._not_found('Series not found in the specified indexer')

        return self._created(series.to_json(), identifier=identifier.slug)
示例#2
0
    def http_post(self, series_slug=None, path_param=None):
        """Add a new series."""
        if series_slug is not None:
            return self._bad_request('Series slug should not be specified')

        data = json_decode(self.request.body)
        if not data or 'id' not in data:
            return self._bad_request('Invalid series data')

        ids = {k: v for k, v in viewitems(data['id']) if k != 'imdb'}
        if len(ids) != 1:
            return self._bad_request('Only 1 indexer identifier should be specified')

        identifier = SeriesIdentifier.from_slug('{slug}{id}'.format(slug=list(ids)[0], id=list(itervalues(ids))[0]))
        if not identifier:
            return self._bad_request('Invalid series identifier')

        series = Series.find_by_identifier(identifier)
        if series:
            return self._conflict('Series already exist added')

        series = Series.from_identifier(identifier)
        if not Series.save_series(series):
            return self._not_found('Series not found in the specified indexer')

        return self._created(series.to_json(), identifier=identifier.slug)
示例#3
0
    def run(self):

        ShowQueueItem.run(self)

        log.info('Starting to add show by {0}',
                 ('show_dir: {0}'.format(self.show_dir) if self.show_dir else
                  'Indexer Id: {0}'.format(self.indexer_id)))

        show_slug = indexer_id_to_slug(self.indexer, self.indexer_id)
        series = Series.from_identifier(SeriesIdentifier.from_slug(show_slug))

        step = []

        # Small helper, to reduce code for messaging
        def message_step(new_step):
            step.append(new_step)
            ws.Message('QueueItemShowAdd', dict(step=step,
                                                **self.to_json)).push()

        try:
            try:
                # Push an update to any open Web UIs through the WebSocket
                message_step('load show from {indexer}'.format(
                    indexer=indexerApi(self.indexer).name))

                api = series.identifier.get_indexer_api(self.options)

                if getattr(api[self.indexer_id], 'seriesname', None) is None:
                    log.error(
                        'Show in {path} has no name on {indexer}, probably searched with the wrong language.',
                        {
                            'path': self.show_dir,
                            'indexer': indexerApi(self.indexer).name
                        })

                    ui.notifications.error(
                        'Unable to add show',
                        'Show in {path} has no name on {indexer}, probably the wrong language.'
                        ' Delete .nfo and manually add the correct language.'.
                        format(path=self.show_dir,
                               indexer=indexerApi(self.indexer).name))
                    self._finish_early()
                    raise SaveSeriesException(
                        'Indexer is missing a showname in this language: {0!r}'
                    )

                series.load_from_indexer(tvapi=api)

                message_step('load info from imdb')
                series.load_imdb_info()
            except IndexerException as error:
                log.warning(
                    'Unable to load series from indexer: {0!r}'.format(error))
                raise SaveSeriesException(
                    'Unable to load series from indexer: {0!r}'.format(error))

            message_step('check if show is already added')

            try:
                message_step('configure show options')
                series.configure(self)
            except KeyError as error:
                log.error(
                    'Unable to add show {series_name} due to an error with one of the provided options: {error}',
                    {
                        'series_name': series.name,
                        'error': error
                    })
                ui.notifications.error(
                    'Unable to add show {series_name} due to an error with one of the provided options: {error}'
                    .format(series_name=series.name, error=error))
                raise SaveSeriesException(
                    'Unable to add show {series_name} due to an error with one of the provided options: {error}'
                    .format(series_name=series.name, error=error))

            except Exception as error:
                log.error('Error trying to configure show: {0}', error)
                log.debug(traceback.format_exc())
                raise

            app.showList.append(series)
            series.save_to_db()

            try:
                message_step('load episodes from {indexer}'.format(
                    indexer=indexerApi(self.indexer).name))
                series.load_episodes_from_indexer(tvapi=api)
                # If we provide a default_status_after through the apiv2 series route options object.
                # set it after we've added the episodes.
                self.default_ep_status = self.options[
                    'default_status_after'] or app.STATUS_DEFAULT_AFTER

            except IndexerException as error:
                log.warning(
                    'Unable to load series episodes from indexer: {0!r}'.
                    format(error))
                raise SaveSeriesException(
                    'Unable to load series episodes from indexer: {0!r}'.
                    format(error))

            message_step('create metadata in show folder')
            series.write_metadata()
            series.update_metadata()
            series.populate_cache()
            build_name_cache(series)  # update internal name cache
            series.flush_episodes()
            series.sync_trakt()

            message_step('add scene numbering')
            series.add_scene_numbering()

        except SaveSeriesException as error:
            log.warning('Unable to add series: {0!r}'.format(error))
            self.success = False
            self._finish_early()
            log.debug(traceback.format_exc())

        default_status = self.options['default_status'] or app.STATUS_DEFAULT
        if statusStrings[default_status] == 'Wanted':
            message_step('trigger backlog search')
            app.backlog_search_scheduler.action.search_backlog([series])

        self.success = True

        ws.Message(
            'showAdded',
            series.to_json(detailed=False)).push()  # Send ws update to client
        message_step('finished')
        self.finish()
示例#4
0
    def run(self):
        """Run QueueItemChangeIndexer queue item."""
        step = []

        # Small helper, to reduce code for messaging
        def message_step(new_step):
            step.append(new_step)

            ws.Message(
                'QueueItemShow',
                dict(step=step,
                     oldShow=self.old_show.to_json() if self.old_show else {},
                     newShow=self.new_show.to_json() if self.new_show else {},
                     **self.to_json)).push()

        ShowQueueItem.run(self)

        def get_show_from_slug(slug):
            identifier = SeriesIdentifier.from_slug(slug)
            if not identifier:
                raise ChangeIndexerException(
                    f'Could not create identifier with slug {slug}')

            show = Series.find_by_identifier(identifier)
            return show

        try:
            # Create reference to old show, before starting the remove it.
            self.old_show = get_show_from_slug(self.old_slug)

            # Store needed options.
            self._store_options()

            # Start of removing the old show
            log.info('{id}: Removing {show}', {
                'id': self.old_show.series_id,
                'show': self.old_show.name
            })
            message_step(f'Removing old show {self.old_show.name}')

            # Need to first remove the episodes from the Trakt collection, because we need the list of
            # Episodes from the db to know which eps to remove.
            if app.USE_TRAKT:
                message_step('Removing episodes from trakt collection')
                try:
                    app.trakt_checker_scheduler.action.remove_show_trakt_library(
                        self.old_show)
                except TraktException as error:
                    log.warning(
                        '{id}: Unable to delete show {show} from Trakt.'
                        ' Please remove manually otherwise it will be added again.'
                        ' Error: {error_msg}', {
                            'id': self.old_show.series_id,
                            'show': self.old_show.name,
                            'error_msg': error
                        })
                except Exception as error:
                    log.exception(
                        'Exception occurred while trying to delete show {show}, error: {error',
                        {
                            'show': self.old_show.name,
                            'error': error
                        })

            self.old_show.delete_show(full=False)

            # Send showRemoved to frontend, so we can remove it from localStorage.
            ws.Message('showRemoved', self.old_show.to_json(
                detailed=False)).push()  # Send ws update to client

            # Double check to see if the show really has been removed, else bail.
            if get_show_from_slug(self.old_slug):
                raise ChangeIndexerException(
                    f'Could not create identifier with slug {self.old_slug}')

            # Start adding the new show
            log.info('Starting to add show by {0}',
                     ('show_dir: {0}'.format(self.show_dir) if self.show_dir
                      else 'New slug: {0}'.format(self.new_slug)))

            self.new_show = Series.from_identifier(
                SeriesIdentifier.from_slug(self.new_slug))

            try:
                # Push an update to any open Web UIs through the WebSocket
                message_step('load show from {indexer}'.format(
                    indexer=indexerApi(self.new_show.indexer).name))

                api = self.new_show.identifier.get_indexer_api(self.options)

                if getattr(api[self.new_show.series_id], 'seriesname',
                           None) is None:
                    log.error(
                        'Show in {path} has no name on {indexer}, probably searched with the wrong language.',
                        {
                            'path': self.show_dir,
                            'indexer': indexerApi(self.new_show.indexer).name
                        })

                    ui.notifications.error(
                        'Unable to add show',
                        'Show in {path} has no name on {indexer}, probably the wrong language.'
                        ' Delete .nfo and manually add the correct language.'.
                        format(path=self.show_dir,
                               indexer=indexerApi(self.new_show.indexer).name))
                    self._finish_early()
                    raise SaveSeriesException(
                        'Indexer is missing a showname in this language: {0!r}'
                    )

                self.new_show.load_from_indexer(tvapi=api)

                message_step('load info from imdb')
                self.new_show.load_imdb_info()
            except IndexerException as error:
                log.warning(
                    'Unable to load series from indexer: {0!r}'.format(error))
                raise SaveSeriesException(
                    'Unable to load series from indexer: {0!r}'.format(error))

            try:
                message_step('configure show options')
                self.new_show.configure(self)
            except KeyError as error:
                log.error(
                    'Unable to add show {series_name} due to an error with one of the provided options: {error}',
                    {
                        'series_name': self.new_show.name,
                        'error': error
                    })
                ui.notifications.error(
                    'Unable to add show {series_name} due to an error with one of the provided options: {error}'
                    .format(series_name=self.new_show.name, error=error))
                raise SaveSeriesException(
                    'Unable to add show {series_name} due to an error with one of the provided options: {error}'
                    .format(series_name=self.new_show.name, error=error))

            except Exception as error:
                log.error('Error trying to configure show: {0}', error)
                log.debug(traceback.format_exc())
                raise

            app.showList.append(self.new_show)
            self.new_show.save_to_db()

            try:
                message_step('load episodes from {indexer}'.format(
                    indexer=indexerApi(self.new_show.indexer).name))
                self.new_show.load_episodes_from_indexer(tvapi=api)
                # If we provide a default_status_after through the apiv2 series route options object.
                # set it after we've added the episodes.
                self.new_show.default_ep_status = self.options[
                    'default_status_after'] or app.STATUS_DEFAULT_AFTER

            except IndexerException as error:
                log.warning(
                    'Unable to load series episodes from indexer: {0!r}'.
                    format(error))
                raise SaveSeriesException(
                    'Unable to load series episodes from indexer: {0!r}'.
                    format(error))

            message_step('create metadata in show folder')
            self.new_show.write_metadata()
            self.new_show.update_metadata()
            self.new_show.populate_cache()
            build_name_cache(self.new_show)  # update internal name cache
            self.new_show.flush_episodes()
            self.new_show.sync_trakt()

            message_step('add scene numbering')
            self.new_show.add_scene_numbering()

            if self.show_dir:
                # If a show dir was passed, this was added as an existing show.
                # For new shows we shouldn't have any files on disk.
                message_step('refresh episodes from disk')
                try:
                    app.show_queue_scheduler.action.refreshShow(self.new_show)
                except CantRefreshShowException as error:
                    log.warning(
                        'Unable to rescan episodes from disk: {0!r}'.format(
                            error))

        except (ChangeIndexerException, SaveSeriesException) as error:
            log.warning('Unable to add series: {0!r}'.format(error))
            self.success = False
            self._finish_early()
            log.debug(traceback.format_exc())

        default_status = self.options['default_status'] or app.STATUS_DEFAULT
        if statusStrings[default_status] == 'Wanted':
            message_step('trigger backlog search')
            app.backlog_search_scheduler.action.search_backlog([self.new_show])

        self.success = True

        ws.Message('showAdded', self.new_show.to_json(
            detailed=False)).push()  # Send ws update to client
        message_step('finished')
        self.finish()