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))
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 + "]")
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()
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."))
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))
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)
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()
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()
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)
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)
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))
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))
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." ))
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))
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() + "]")
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))
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))
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 + "]")