Ejemplo n.º 1
0
    def run(self):
        self.started = True

        show_object = find_show(self.series_id, self.series_provider_id)
        if not show_object:
            return

        episode_object = show_object.get_episode(self.season, self.episode)

        try:
            sickrage.app.log.info(
                "Starting backlog search for: [{}] S{:02d}E{:02d}".format(
                    show_object.name, self.season, self.episode))

            WebSocketMessage(
                'SEARCH_QUEUE_STATUS_UPDATED', {
                    'seriesSlug': show_object.slug,
                    'episodeId': episode_object.episode_id,
                    'searchQueueStatus': episode_object.search_queue_status
                }).push()

            search_result = search_providers(self.series_id,
                                             self.series_provider_id,
                                             self.season,
                                             self.episode,
                                             manualSearch=False)

            if search_result:
                snatch = all([(search_result.series_id, search_result.season,
                               episode)
                              not in sickrage.app.search_queue.SNATCH_HISTORY
                              for episode in search_result.episodes])

                if snatch:
                    [
                        sickrage.app.search_queue.SNATCH_HISTORY.append(
                            (search_result.series_id, search_result.season,
                             episode)) for episode in search_result.episodes
                    ]

                    sickrage.app.log.info("Downloading {} from {}".format(
                        search_result.name, search_result.provider.name))
                    snatch_episode(search_result)
            else:
                sickrage.app.log.info(
                    "Unable to find search results for: [{}] S{:02d}E{:02d}".
                    format(show_object.name, self.season, self.episode))
        except Exception:
            sickrage.app.log.debug(traceback.format_exc())
        finally:
            WebSocketMessage(
                'SEARCH_QUEUE_STATUS_UPDATED', {
                    'seriesSlug': show_object.slug,
                    'episodeId': episode_object.episode_id,
                    'searchQueueStatus': episode_object.search_queue_status
                }).push()

            sickrage.app.log.info(
                "Finished backlog search for: [{}] S{:02d}E{:02d}".format(
                    show_object.name, self.season, self.episode))
Ejemplo n.º 2
0
    def run(self):
        self.started = True

        show_object = find_show(self.series_id, self.series_provider_id)
        if not show_object:
            return

        episode_object = show_object.get_episode(self.season, self.episode)

        try:
            sickrage.app.log.info("Starting daily search for: [" +
                                  show_object.name + "]")

            WebSocketMessage(
                'SEARCH_QUEUE_STATUS_UPDATED', {
                    'seriesSlug': show_object.slug,
                    'episodeId': episode_object.episode_id,
                    'searchQueueStatus': episode_object.search_queue_status
                }).push()

            search_result = search_providers(
                self.series_id,
                self.series_provider_id,
                self.season,
                self.episode,
                cacheOnly=sickrage.app.config.general.enable_rss_cache)

            if search_result:
                snatch = all([(search_result.series_id, search_result.season,
                               episode)
                              not in sickrage.app.search_queue.SNATCH_HISTORY
                              for episode in search_result.episodes])

                if snatch:
                    [
                        sickrage.app.search_queue.SNATCH_HISTORY.append(
                            (search_result.series_id, search_result.season,
                             episode)) for episode in search_result.episodes
                    ]

                    sickrage.app.log.info("Downloading " + search_result.name +
                                          " from " +
                                          search_result.provider.name)
                    snatch_episode(search_result)
            else:
                sickrage.app.log.info("Unable to find search results for: [" +
                                      show_object.name + "]")
        except Exception:
            sickrage.app.log.debug(traceback.format_exc())
        finally:
            WebSocketMessage(
                'SEARCH_QUEUE_STATUS_UPDATED', {
                    'seriesSlug': show_object.slug,
                    'episodeId': episode_object.episode_id,
                    'searchQueueStatus': episode_object.search_queue_status
                }).push()

            sickrage.app.log.info("Finished daily search for: [" +
                                  show_object.name + "]")
Ejemplo n.º 3
0
 def finish(self):
     show_obj = find_show(self.series_id, self.series_provider_id)
     if show_obj:
         WebSocketMessage(
             'SHOW_QUEUE_STATUS_UPDATED', {
                 'seriesSlug': show_obj.slug,
                 'showQueueStatus': show_obj.show_queue_status
             }).push()
     else:
         WebSocketMessage(
             'SHOW_QUEUE_STATUS_UPDATED', {
                 'seriesSlug':
                 f'{self.series_id}-{self.series_provider_id.slug}',
                 'action': self.action.name
             }).push()
Ejemplo n.º 4
0
    def update(self, webui=False):
        if self.updater:
            # check if its safe to update
            if not self.safe_to_update():
                return False

            # backup
            if not self.backup():
                return False

            # check for updates
            if not self.updater.need_update():
                return False

            # attempt update
            if self.updater.update():
                # Clean up after update
                to_clean = os.path.join(sickrage.app.cache_dir, 'mako')

                for root, dirs, files in os.walk(to_clean, topdown=False):
                    [os.remove(os.path.join(root, name)) for name in files]
                    [shutil.rmtree(os.path.join(root, name)) for name in dirs]

                sickrage.app.config.view_changelog = True

                if webui:
                    WebSocketMessage('task', {'cmd': 'restart'}).push()

                return True

            if webui:
                sickrage.app.alerts.error(
                    _("Updater"),
                    _("Update wasn't successful, not restarting. Check your log for more "
                      "information."))
Ejemplo n.º 5
0
    def run(self):
        super(ShowTaskRefresh, self).run()

        start_time = time.time()

        tv_show = find_show(self.series_id, self.series_provider_id)

        sickrage.app.log.info("Performing refresh for show: {}".format(
            tv_show.name))

        tv_show.refresh_dir()
        tv_show.write_metadata(force=self.force)
        tv_show.populate_cache(force=self.force)

        # Load XEM data to DB for show
        # xem_refresh(show.series_id, show.series_provider_id)

        tv_show.last_refresh = datetime.datetime.now()

        tv_show.save()

        WebSocketMessage(
            'SHOW_REFRESHED', {
                'seriesSlug': tv_show.slug,
                'series': tv_show.to_json(episodes=True, details=True)
            }).push()

        sickrage.app.log.info("Finished refresh in {}s for show: {}".format(
            round(time.time() - start_time, 2), tv_show.name))
Ejemplo n.º 6
0
    def post(self, series_slug):
        """Rename list of episodes"
        ---
        tags: [Series]
        summary: Rename list of episodes
        description: Rename list of episodes
        parameters:
        - in: path
          schema:
            SeriesSlugPath
        responses:
          200:
            description: Success payload
            content:
              application/json:
                schema:
                  EpisodesRenameSuccessSchema
          400:
            description: Bad request; Check `errors` for any validation errors
            content:
              application/json:
                schema:
                  BadRequestSchema
          401:
            description: Returned if your JWT token is missing or expired
            content:
              application/json:
                schema:
                  NotAuthorizedSchema
        """
        data = json_decode(self.request.body)

        renamed_episodes = []

        series = find_show_by_slug(series_slug)
        if series is None:
            return self._not_found(
                error=
                f"Unable to find the specified series using slug: {series_slug}"
            )

        if not os.path.isdir(series.location):
            return self._bad_request(
                error=
                "Can't rename episodes when the show location does not exist")

        for episode_id in data.get('episodeIdList', []):
            episode = find_episode(episode_id, series.series_provider_id)
            if episode:
                episode.rename()
                renamed_episodes.append(episode.episode_id)

        if len(renamed_episodes) > 0:
            WebSocketMessage('SHOW_RENAMED', {
                'seriesSlug': series.slug
            }).push()

        return self.json_response(renamed_episodes)
Ejemplo n.º 7
0
 def finish(self):
     show_object = find_show(self.series_id, self.series_provider_id)
     episode_object = show_object.get_episode(self.season, self.episode)
     WebSocketMessage(
         'SEARCH_QUEUE_STATUS_UPDATED', {
             'seriesSlug': show_object.slug,
             'episodeId': episode_object.episode_id,
             'searchQueueStatus': episode_object.search_queue_status
         }).push()
Ejemplo n.º 8
0
 def _finish_early(self):
     try:
         sickrage.app.show_queue.remove_show(self.series_id,
                                             self.series_provider_id)
     except CantRemoveShowException:
         WebSocketMessage('SHOW_REMOVED', {
             'seriesSlug':
             f'{self.series_id}-{self.series_provider_id.slug}'
         }).push()
Ejemplo n.º 9
0
    def error(self, title, message=""):
        """
        Add an error notification to the queue

        title: The title of the notification
        message: The message portion of the notification
        """

        n = Notification(title, message, ERROR)
        if not WebSocketMessage('notification', n.data).push():
            self._errors.append(n)
Ejemplo n.º 10
0
    def message(self, title, message=""):
        """
        Add a regular notification to the queue

        title: The title of the notification
        message: The message portion of the notification
        """

        n = Notification(title, message, MESSAGE)
        if not WebSocketMessage('notification', n.data).push():
            self._messages.append(n)
Ejemplo n.º 11
0
    def run(self):
        super(ShowTaskSubtitle, self).run()

        tv_show = find_show(self.series_id, self.series_provider_id)

        sickrage.app.log.info(
            "Started downloading subtitles for show: {}".format(tv_show.name))

        tv_show.download_subtitles()

        WebSocketMessage(
            'SHOW_SUBTITLED', {
                'seriesSlug': tv_show.slug,
                'series': tv_show.to_json(episodes=True, details=True)
            }).push()

        sickrage.app.log.info(
            "Finished downloading subtitles for show: {}".format(tv_show.name))
Ejemplo n.º 12
0
    def run(self):
        super(ShowTaskRename, self).run()

        tv_show = find_show(self.series_id, self.series_provider_id)

        sickrage.app.log.info("Performing renames for show: {}".format(
            tv_show.name))

        if not os.path.isdir(tv_show.location):
            sickrage.app.log.warning("Can't perform rename on " +
                                     tv_show.name +
                                     " when the show dir is missing.")
            return

        ep_obj_rename_list = []

        for cur_ep_obj in (x for x in tv_show.episodes if x.location):
            # Only want to rename if we have a location
            if cur_ep_obj.location:
                if cur_ep_obj.related_episodes:
                    # do we have one of multi-episodes in the rename list already
                    have_already = False
                    for cur_related_ep in cur_ep_obj.related_episodes + [
                            cur_ep_obj
                    ]:
                        if cur_related_ep in ep_obj_rename_list:
                            have_already = True
                            break
                    if not have_already:
                        ep_obj_rename_list.append(cur_ep_obj)
                else:
                    ep_obj_rename_list.append(cur_ep_obj)

        for cur_ep_obj in ep_obj_rename_list:
            cur_ep_obj.rename()

        WebSocketMessage(
            'SHOW_RENAMED', {
                'seriesSlug': tv_show.slug,
                'series': tv_show.to_json(episodes=True, details=True)
            }).push()

        sickrage.app.log.info("Finished renames for show: {}".format(
            tv_show.name))
Ejemplo n.º 13
0
    def update(self, webui=False):
        # check if updater only allows manual updates
        if self.updater.manual_update:
            return False

        # check for updates
        if not self.updater.need_update():
            return False

        # check if its safe to update
        if not self.safe_to_update():
            return False

        # backup
        if sickrage.app.config.general.backup_on_update and not self.backup():
            return False

        # attempt update
        if self.updater.update():
            # Clean up after update
            to_clean = os.path.join(sickrage.app.cache_dir, 'mako')

            for root, dirs, files in os.walk(to_clean, topdown=False):
                [os.remove(os.path.join(root, name)) for name in files]
                [shutil.rmtree(os.path.join(root, name)) for name in dirs]

            sickrage.app.config.general.view_changelog = True

            if webui:
                WebSocketMessage(
                    'redirect', {
                        'url':
                        f'{sickrage.app.config.general.web_root}/home/restart/?pid={sickrage.app.pid}'
                    }).push()

            return True

        if webui:
            sickrage.app.alerts.error(
                _("Updater"),
                _("Update wasn't successful, not restarting. Check your log for more information."
                  ))
Ejemplo n.º 14
0
    def run(self):
        super(ShowTaskForceRemove, self).run()

        show_obj = find_show(self.series_id, self.series_provider_id)

        sickrage.app.log.info("Removing show: {}".format(show_obj.name))

        show_obj.delete_show(full=self.full)

        if sickrage.app.config.trakt.enable:
            try:
                sickrage.app.trakt_searcher.remove_show_from_trakt_library(
                    show_obj)
            except Exception as e:
                sickrage.app.log.warning(
                    "Unable to delete show from Trakt: %s. Error: %s" %
                    (show_obj.name, e))

        WebSocketMessage('SHOW_REMOVED', {'seriesSlug': show_obj.slug}).push()

        sickrage.app.log.info("Finished removing show: {}".format(
            show_obj.name))
Ejemplo n.º 15
0
    def run(self):
        self.started = True

        sickrage.app.search_queue.TASK_HISTORY[self.id] = {
            'season': self.season,
            'episode': self.episode
        }

        show_object = find_show(self.series_id, self.series_provider_id)
        if not show_object:
            return

        episode_object = show_object.get_episode(self.season, self.episode)

        WebSocketMessage(
            'SEARCH_QUEUE_STATUS_UPDATED', {
                'seriesSlug': show_object.slug,
                'episodeId': episode_object.episode_id,
                'searchQueueStatus': episode_object.search_queue_status
            }).push()

        try:
            sickrage.app.log.info("Starting manual search for: [" +
                                  episode_object.pretty_name() + "]")

            search_result = search_providers(
                self.series_id,
                self.series_provider_id,
                self.season,
                self.episode,
                manualSearch=True,
                downCurQuality=self.downCurQuality)

            if search_result:
                [
                    sickrage.app.search_queue.SNATCH_HISTORY.append(
                        (search_result.series_id, search_result.season,
                         episode)) for episode in search_result.episodes
                ]

                sickrage.app.log.info("Downloading " + search_result.name +
                                      " from " + search_result.provider.name)
                self.success = snatch_episode(search_result)

                WebSocketMessage(
                    'EPISODE_UPDATED', {
                        'seriesSlug': show_object.slug,
                        'episodeId': episode_object.episode_id,
                        'episode': episode_object.to_json()
                    }).push()
            else:
                sickrage.app.alerts.message(
                    _('No downloads were found'),
                    _("Couldn't find a download for <i>%s</i>") %
                    episode_object.pretty_name())

                sickrage.app.log.info("Unable to find a download for: [" +
                                      episode_object.pretty_name() + "]")
        except Exception:
            sickrage.app.log.debug(traceback.format_exc())
        finally:
            sickrage.app.log.info("Finished manual search for: [" +
                                  episode_object.pretty_name() + "]")
Ejemplo n.º 16
0
    def run(self):
        super(ShowTaskUpdate, self).run()

        show_obj = find_show(self.series_id, self.series_provider_id)

        start_time = time.time()

        sickrage.app.log.info("Performing updates for show: {}".format(
            show_obj.name))

        try:
            sickrage.app.log.debug("Retrieving show info from " +
                                   show_obj.series_provider.name + "")
            show_obj.load_from_series_provider(cache=False)
        except SeriesProviderAttributeNotFound as e:
            sickrage.app.log.warning("Data retrieved from " +
                                     show_obj.series_provider.name +
                                     " was incomplete, aborting: {}".format(e))
            return
        except SeriesProviderException as e:
            sickrage.app.log.warning("Unable to contact " +
                                     show_obj.series_provider.name +
                                     ", aborting: {}".format(e))
            return

        try:
            sickrage.app.log.debug(
                "Attempting to retrieve show info from IMDb")
            show_obj.load_imdb_info()
        except Exception as e:
            sickrage.app.log.warning(
                "Error loading IMDb info for {}: {}".format(
                    show_obj.series_provider.name, e))

        # get episodes from database
        db_episodes = {}
        for data in show_obj.episodes:
            if data.season not in db_episodes:
                db_episodes[data.season] = {}
            db_episodes[data.season].update({data.episode: True})

        # get episodes from a series provider
        try:
            series_provider_episodes = show_obj.load_episodes_from_series_provider(
            )
        except SeriesProviderException as e:
            sickrage.app.log.warning(
                "Unable to get info from " + show_obj.series_provider.name +
                ", the show info will not be refreshed: {}".format(e))
            series_provider_episodes = None

        if not series_provider_episodes:
            sickrage.app.log.warning("No data returned from " +
                                     show_obj.series_provider.name +
                                     ", unable to update this show")
        else:
            # for each ep we found on series_provider_id delete it from the DB list
            for curSeason in series_provider_episodes:
                for curEpisode in series_provider_episodes[curSeason]:
                    if curSeason in db_episodes and curEpisode in db_episodes[
                            curSeason]:
                        del db_episodes[curSeason][curEpisode]

            # remaining episodes in the DB list are not on the series_provider_id, just delete them from the DB
            for curSeason in db_episodes:
                for curEpisode in db_episodes[curSeason]:
                    sickrage.app.log.info("Permanently deleting episode " +
                                          str(curSeason) + "x" +
                                          str(curEpisode) +
                                          " from the database")
                    try:
                        show_obj.delete_episode(curSeason, curEpisode)
                    except EpisodeDeletedException:
                        continue

        show_obj.retrieve_scene_exceptions()

        WebSocketMessage(
            'SHOW_UPDATED', {
                'seriesSlug': show_obj.slug,
                'series': show_obj.to_json(episodes=True, details=True)
            }).push()

        sickrage.app.log.info("Finished updates in {}s for show: {}".format(
            round(time.time() - start_time, 2), show_obj.name))
Ejemplo n.º 17
0
    def run(self):
        super(ShowTaskAdd, self).run()

        start_time = time.time()

        sickrage.app.log.info(
            "Started adding show {} from show dir: {}".format(
                self.show_name, self.show_dir))

        s = sickrage.app.series_providers[self.series_provider_id].search(
            self.series_id,
            language=self.lang
            or sickrage.app.config.general.series_provider_default_language,
            enable_cache=False)

        if not s:
            sickrage.app.alerts.error(
                _("Unable to add show"),
                _("Unable to look up the show in {} on {} using ID {}, not using the NFO. Delete .nfo and try adding "
                  "manually again.").format(
                      self.show_dir, sickrage.app.series_providers[
                          self.series_provider_id].name, self.series_id))

            if sickrage.app.config.trakt.enable:
                title = self.show_dir.split("/")[-1]

                data = {
                    'shows': [{
                        'title': title,
                        'ids': {
                            sickrage.app.series_providers[self.series_provider_id].trakt_id:
                            self.series_id
                        }
                    }]
                }

                TraktAPI()["sync/watchlist"].remove(data)

            return self._finish_early()

        # this usually only happens if they have an NFO in their show dir which gave us a series id that has no
        # proper english version of the show
        try:
            s.seriesname
        except AttributeError:
            sickrage.app.log.warning(
                f"Show in {self.show_dir} has no name on {sickrage.app.series_providers[self.series_provider_id].name}, "
                f"probably the wrong language used to search with")

            sickrage.app.alerts.error(
                _("Unable to add show"),
                _(f"Show in {self.show_dir} has no name on {sickrage.app.series_providers[self.series_provider_id].name}, "
                  f"probably the wrong language. Delete .nfo and add manually in the correct language"
                  ))

            return self._finish_early()

        # if the show has no episodes/seasons
        if not len(s):
            sickrage.app.log.warning("Show " + str(s['seriesname']) +
                                     " is on " +
                                     str(sickrage.app.series_providers[
                                         self.series_provider_id].name) +
                                     "but contains no season/episode "
                                     "data.")
            sickrage.app.alerts.error(
                _("Unable to add show"),
                _("Show ") + str(s['seriesname']) + _(" is on ") +
                str(sickrage.app.series_providers[
                    self.series_provider_id].name) +
                _(" but contains no season/episode data."))
            return self._finish_early()

        try:
            # add show to database
            show_obj = TVShow(self.series_id,
                              self.series_provider_id,
                              lang=self.lang,
                              location=self.show_dir)

            # set up initial values
            show_obj.subtitles = self.subtitles if self.subtitles is not None else sickrage.app.config.subtitles.default
            show_obj.sub_use_sr_metadata = self.sub_use_sr_metadata if self.sub_use_sr_metadata is not None else False
            show_obj.quality = self.quality if self.quality is not None else sickrage.app.config.general.quality_default
            show_obj.flatten_folders = self.flatten_folders if self.flatten_folders is not None else sickrage.app.config.general.flatten_folders_default
            show_obj.scene = self.scene if self.scene is not None else sickrage.app.config.general.scene_default
            show_obj.anime = self.anime if self.anime is not None else sickrage.app.config.general.anime_default
            show_obj.dvd_order = self.dvd_order if self.dvd_order is not None else False
            show_obj.search_format = self.search_format if self.search_format is not None else sickrage.app.config.general.search_format_default
            show_obj.skip_downloaded = self.skip_downloaded if self.skip_downloaded is not None else sickrage.app.config.general.skip_downloaded_default
            show_obj.paused = self.paused if self.paused is not None else False

            # set up default new/missing episode status
            sickrage.app.log.info(
                "Setting all current episodes to the specified default status: "
                + str(self.default_status))
            show_obj.default_ep_status = self.default_status

            # save to database
            show_obj.save()

            if show_obj.anime:
                if self.blacklist:
                    show_obj.release_groups.set_black_keywords(self.blacklist)
                if self.whitelist:
                    show_obj.release_groups.set_white_keywords(self.whitelist)
        except SeriesProviderException as e:
            sickrage.app.log.warning(
                _("Unable to add show due to an error with ") +
                sickrage.app.series_providers[self.series_provider_id].name +
                ": {}".format(e))
            sickrage.app.alerts.error(
                _("Unable to add show due to an error with ") +
                sickrage.app.series_providers[self.series_provider_id].name +
                "")
            return self._finish_early()
        except MultipleShowObjectsException:
            sickrage.app.log.warning(
                _("The show in ") + self.show_dir +
                _(" is already in your show list, skipping"))
            sickrage.app.alerts.error(
                _('Show skipped'),
                _("The show in ") + self.show_dir +
                _(" is already in your show list"))
            return self._finish_early()
        except Exception as e:
            sickrage.app.log.error(_("Error trying to add show: {}").format(e))
            sickrage.app.log.debug(traceback.format_exc())
            raise self._finish_early()

        try:
            sickrage.app.log.debug(
                _("Attempting to retrieve show info from IMDb"))
            show_obj.load_imdb_info()
        except Exception as e:
            sickrage.app.log.debug(_("Error loading IMDb info: {}").format(e))
            sickrage.app.log.debug(traceback.format_exc())

        try:
            show_obj.load_episodes_from_series_provider()
        except Exception as e:
            sickrage.app.log.debug(
                _("Error with ") + show_obj.series_provider.name +
                _(", not creating episode list: {}").format(e))
            sickrage.app.log.debug(traceback.format_exc())

        try:
            show_obj.load_episodes_from_dir()
        except Exception as e:
            sickrage.app.log.debug(
                "Error searching dir for episodes: {}".format(e))
            sickrage.app.log.debug(traceback.format_exc())

        show_obj.write_metadata(force=True)
        show_obj.populate_cache()

        if sickrage.app.config.trakt.enable:
            # if there are specific episodes that need to be added by trakt
            sickrage.app.trakt_searcher.manage_new_show(show_obj)

            # add show to trakt.tv library
            if sickrage.app.config.trakt.sync:
                sickrage.app.trakt_searcher.add_show_to_trakt_library(show_obj)

            if sickrage.app.config.trakt.sync_watchlist:
                sickrage.app.log.info("update watchlist")
                sickrage.app.notification_providers['trakt'].update_watchlist(
                    show_obj)

        # Retrieve scene exceptions
        show_obj.retrieve_scene_exceptions()

        # Load XEM data to DB for show
        xem_refresh(show_obj.series_id,
                    show_obj.series_provider_id,
                    force=True)

        # check if show has XEM mapping so we can determine if searches should go by scene numbering or series_provider_id
        # numbering.
        # if not self.scene and get_xem_numbering_for_show(show_obj.series_id, show_obj.series_provider_id):
        #     show_obj.scene = 1

        # if they set default ep status to WANTED then run the backlog to search for episodes
        if show_obj.default_ep_status == EpisodeStatus.WANTED:
            sickrage.app.log.info(
                _("Launching backlog for this show since it has episodes that are WANTED"
                  ))
            sickrage.app.backlog_searcher.search_backlog(
                show_obj.series_id, show_obj.series_provider_id)

        show_obj.default_ep_status = self.default_status_after

        show_obj.save()

        WebSocketMessage('SHOW_ADDED', {
            'seriesSlug': show_obj.slug,
            'series': show_obj.to_json(progress=True)
        }).push()

        sickrage.app.log.info(
            "Finished adding show {} in {}s from show dir: {}".format(
                self.show_name, round(time.time() - start_time, 2),
                self.show_dir))
Ejemplo n.º 18
0
    def run(self):
        self.started = True

        sickrage.app.search_queue.TASK_HISTORY[self.id] = {
            'season': self.season,
            'episode': self.episode
        }

        show_object = find_show(self.series_id, self.series_provider_id)
        if not show_object:
            return

        episode_object = show_object.get_episode(self.season, self.episode)

        try:
            sickrage.app.log.info("Starting failed download search for: [" +
                                  episode_object.name + "]")

            WebSocketMessage(
                'SEARCH_QUEUE_STATUS_UPDATED', {
                    'seriesSlug': show_object.slug,
                    'episodeId': episode_object.episode_id,
                    'searchQueueStatus': episode_object.search_queue_status
                }).push()

            sickrage.app.log.info("Marking episode as bad: [" +
                                  episode_object.pretty_name() + "]")

            FailedHistory.mark_failed(self.series_id, self.series_provider_id,
                                      self.season, self.episode)

            (release, provider) = FailedHistory.find_failed_release(
                self.series_id, self.series_provider_id, self.season,
                self.episode)
            if release:
                FailedHistory.log_failed(release)
                History.log_failed(self.series_id, self.series_provider_id,
                                   self.season, self.episode, release,
                                   provider)

            FailedHistory.revert_failed_episode(self.series_id,
                                                self.series_provider_id,
                                                self.season, self.episode)

            search_result = search_providers(self.series_id,
                                             self.series_provider_id,
                                             self.season,
                                             self.episode,
                                             manualSearch=True,
                                             downCurQuality=False)

            if search_result:
                snatch = all([(search_result.series_id, search_result.season,
                               episode)
                              not in sickrage.app.search_queue.SNATCH_HISTORY
                              for episode in search_result.episodes])

                if snatch:
                    [
                        sickrage.app.search_queue.SNATCH_HISTORY.append(
                            (search_result.series_id, search_result.season,
                             episode)) for episode in search_result.episodes
                    ]

                    sickrage.app.log.info("Downloading " + search_result.name +
                                          " from " +
                                          search_result.provider.name)
                    snatch_episode(search_result)
        except Exception:
            sickrage.app.log.debug(traceback.format_exc())
        finally:
            WebSocketMessage(
                'SEARCH_QUEUE_STATUS_UPDATED', {
                    'seriesSlug': show_object.slug,
                    'episodeId': episode_object.episode_id,
                    'searchQueueStatus': episode_object.search_queue_status
                }).push()

            sickrage.app.log.info("Finished failed download search for: [" +
                                  show_object.name + "]")