def run(self): self.started = True try: sickrage.app.log.info("Starting failed download search for: [" + self.show.name + "]") for epObj in self.segment: sickrage.app.log.info("Marking episode as bad: [" + epObj.pretty_name() + "]") FailedHistory.markFailed(epObj) (release, provider) = FailedHistory.findFailedRelease(epObj) if release: FailedHistory.logFailed(release) History.logFailed(epObj, release, provider) FailedHistory.revertFailedEpisode(epObj) search_result = searchProviders(self.show, self.segment, manualSearch=True, downCurQuality=False) if search_result: for result in search_result: # just use the first result for now sickrage.app.log.info("Downloading " + result.name + " from " + result.provider.name) snatchEpisode(result) # give the CPU a break time.sleep(cpu_presets[sickrage.app.config.cpu_preset]) except Exception: sickrage.app.log.debug(traceback.format_exc()) finally: sickrage.app.log.info("Finished failed download search for: [" + self.show.name + "]") # Keep a list with the 100 last executed searches fifo(MANUAL_SEARCH_HISTORY, self, MANUAL_SEARCH_HISTORY_SIZE)
def downloadSubtitles(subtitles_info): existing_subtitles = subtitles_info[b'subtitles'] # First of all, check if we need subtitles languages = getNeededLanguages(existing_subtitles) if not languages: sickrage.LOGGER.debug('%s: No missing subtitles for S%02dE%02d' % ( subtitles_info[b'show.indexerid'], subtitles_info[b'season'], subtitles_info[b'episode'])) return existing_subtitles, None subtitles_path = getSubtitlesPath(subtitles_info[b'location']).encode(sickrage.SYS_ENCODING) video_path = subtitles_info[b'location'].encode(sickrage.SYS_ENCODING) providers = getEnabledServiceList() try: video = subliminal.scan_video(video_path, subtitles=False, embedded_subtitles=False) except Exception: sickrage.LOGGER.debug('%s: Exception caught in subliminal.scan_video for S%02dE%02d' % (subtitles_info[b'show.indexerid'], subtitles_info[b'season'], subtitles_info[b'episode'])) return existing_subtitles, None provider_configs = {'addic7ed': {'username': sickrage.ADDIC7ED_USER, 'password': sickrage.ADDIC7ED_PASS}, 'legendastv': {'username': sickrage.LEGENDASTV_USER, 'password': sickrage.LEGENDASTV_PASS}, 'opensubtitles': {'username': sickrage.OPENSUBTITLES_USER, 'password': sickrage.OPENSUBTITLES_PASS}} pool = subliminal.api.ProviderPool(providers=providers, provider_configs=provider_configs) try: subtitles_list = pool.list_subtitles(video, languages) if not subtitles_list: sickrage.LOGGER.debug('%s: No subtitles found for S%02dE%02d on any provider' % ( subtitles_info[b'show.indexerid'], subtitles_info[b'season'], subtitles_info[b'episode'])) return existing_subtitles, None found_subtitles = pool.download_best_subtitles(subtitles_list, video, languages=languages, hearing_impaired=sickrage.SUBTITLES_HEARING_IMPAIRED, only_one=not sickrage.SUBTITLES_MULTI) save_subtitles(video, found_subtitles, directory=subtitles_path, single=not sickrage.SUBTITLES_MULTI) if not sickrage.EMBEDDED_SUBTITLES_ALL and sickrage.SUBTITLES_EXTRA_SCRIPTS and video_path.endswith( ('.mkv', '.mp4')): run_subs_extra_scripts(subtitles_info, found_subtitles, video, single=not sickrage.SUBTITLES_MULTI) current_subtitles = subtitlesLanguages(video_path)[0] new_subtitles = frozenset(current_subtitles).difference(existing_subtitles) except Exception: sickrage.LOGGER.info("Error occurred when downloading subtitles for: %s" % video_path) sickrage.LOGGER.error(traceback.format_exc()) return existing_subtitles, None if sickrage.SUBTITLES_HISTORY: for subtitle in found_subtitles: sickrage.LOGGER.debug('history.logSubtitle %s, %s' % (subtitle.provider_name, subtitle.language.opensubtitles)) History.logSubtitle(subtitles_info[b'show.indexerid'], subtitles_info[b'season'], subtitles_info[b'episode'], subtitles_info[b'status'], subtitle) return current_subtitles, new_subtitles
def run(self): super(FailedQueueItem, self).run() self.started = True try: for epObj in self.segment: sickrage.srCore.srLogger.info("Marking episode as bad: [" + epObj.prettyName() + "]") FailedHistory.markFailed(epObj) (release, provider) = FailedHistory.findFailedRelease(epObj) if release: FailedHistory.logFailed(release) History.logFailed(epObj, release, provider) FailedHistory.revertFailedEpisode(epObj) sickrage.srCore.srLogger.info("Beginning failed download search for: [" + epObj.prettyName() + "]") # If it is wanted, self.downCurQuality doesnt matter # if it isnt wanted, we need to make sure to not overwrite the existing ep that we reverted to! searchResult = searchProviders(self.show, self.segment, True, False) if searchResult: for result in searchResult: # just use the first result for now sickrage.srCore.srLogger.info("Downloading " + result.name + " from " + result.provider.name) snatchEpisode(result) # give the CPU a break time.sleep(cpu_presets[sickrage.srCore.srConfig.CPU_PRESET]) except Exception: sickrage.srCore.srLogger.debug(traceback.format_exc()) ### Keep a list with the 100 last executed searches fifo(MANUAL_SEARCH_HISTORY, self, MANUAL_SEARCH_HISTORY_SIZE)
def run(self): self.started = True show_object = find_show(self.show_id) episode_object = show_object.get_episode(self.season, self.episode) try: sickrage.app.log.info("Starting failed download search for: [" + episode_object.name + "]") sickrage.app.log.info("Marking episode as bad: [" + episode_object.pretty_name() + "]") FailedHistory.mark_failed(self.show_id, self.season, self.episode) (release, provider) = FailedHistory.find_failed_release( self.show_id, self.season, self.episode) if release: FailedHistory.log_failed(release) History.log_failed(self.show_id, self.season, self.episode, release, provider) FailedHistory.revert_failed_episode(self.show_id, self.season, self.episode) search_result = search_providers(self.show_id, self.season, self.episode, manualSearch=True, downCurQuality=False) if search_result: snatch = all([(search_result.show_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.fifo( sickrage.app.search_queue.SNATCH_HISTORY, (search_result.show_id, search_result.season, episode), sickrage.app.search_queue.SNATCH_HISTORY_SIZE) 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: sickrage.app.log.info("Finished failed download search for: [" + show_object.name + "]") sickrage.app.search_queue.fifo( sickrage.app.search_queue.MANUAL_SEARCH_HISTORY, self, sickrage.app.search_queue.MANUAL_SEARCH_HISTORY_SIZE)
def get(self): """Get snatch and download history" --- tags: [History] summary: Get snatch and download history description: Get snatch and download history responses: 200: description: Success payload content: application/json: schema: HistorySuccessSchema 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 404: description: Returned if the given series slug does not exist or no series results. content: application/json: schema: NotFoundSchema """ limit = int(self.get_argument('limit', sickrage.app.config.gui.history_limit or 100)) results = [] for row in History().get(limit): status, quality = Quality.split_composite_status(int(row["action"])) # if self.type and not status.lower() == self.type: # continue row["status"] = status.display_name row["quality"] = quality.name row["date"] = datetime.datetime.fromordinal(row["date"].toordinal()).timestamp() del row["action"] row["series_id"] = row.pop("series_id") row['series_provider_id'] = row['series_provider_id'].name row["resource_path"] = os.path.dirname(row["resource"]) row["resource"] = os.path.basename(row["resource"]) row = convert_dict_keys_to_camelcase(row) results.append(row) return self.json_response(results)
def download_subtitles(episode): existing_subtitles = episode.subtitles # First of all, check if we need subtitles languages = get_needed_languages(existing_subtitles) if not languages: sickrage.app.log.debug('%s: No missing subtitles for S%02dE%02d' % ( episode.show.indexerid, episode.season, episode.episode)) return existing_subtitles, None subtitles_path = get_subtitles_path(episode.location) video_path = episode.location providers = getEnabledServiceList() video = get_video(video_path, subtitles_path=subtitles_path, episode=episode) if not video: sickrage.app.log.debug('%s: Exception caught in subliminal.scan_video for S%02dE%02d' % (episode.show.indexerid, episode.season, episode.episode)) return existing_subtitles, None provider_configs = { 'addic7ed': {'username': sickrage.app.config.addic7ed_user, 'password': sickrage.app.config.addic7ed_pass}, 'itasa': {'username': sickrage.app.config.itasa_user, 'password': sickrage.app.config.itasa_pass}, 'legendastv': {'username': sickrage.app.config.legendastv_user, 'password': sickrage.app.config.legendastv_pass}, 'opensubtitles': {'username': sickrage.app.config.opensubtitles_user, 'password': sickrage.app.config.opensubtitles_pass}} pool = subliminal.ProviderPool(providers=providers, provider_configs=provider_configs) try: subtitles_list = pool.list_subtitles(video, languages) if not subtitles_list: sickrage.app.log.debug('%s: No subtitles found for S%02dE%02d on any provider' % ( episode.show.indexerid, episode.season, episode.episode)) return existing_subtitles, None found_subtitles = pool.download_best_subtitles(subtitles_list, video, languages=languages, hearing_impaired=sickrage.app.config.subtitles_hearing_impaired, only_one=not sickrage.app.config.subtitles_multi) save_subtitles(video, found_subtitles, directory=subtitles_path, single=not sickrage.app.config.subtitles_multi) if not sickrage.app.config.embedded_subtitles_all and sickrage.app.config.subtitles_extra_scripts and video_path.endswith( ('.mkv', '.mp4')): run_subs_extra_scripts(episode, found_subtitles, video, single=not sickrage.app.config.subtitles_multi) new_subtitles = sorted({subtitle.language.opensubtitles for subtitle in found_subtitles}) current_subtitles = sorted({subtitle for subtitle in new_subtitles + existing_subtitles if subtitle}) if not sickrage.app.config.subtitles_multi and len(found_subtitles) == 1: new_code = found_subtitles[0].language.opensubtitles if new_code not in existing_subtitles: current_subtitles.remove(new_code) current_subtitles.append('und') except Exception: sickrage.app.log.info("Error occurred when downloading subtitles for: %s" % video_path) sickrage.app.log.error(traceback.format_exc()) return existing_subtitles, None if sickrage.app.config.subtitles_history: from sickrage.core.tv.show.history import History for subtitle in found_subtitles: sickrage.app.log.debug( 'history.logSubtitle %s, %s' % (subtitle.provider_name, subtitle.language.opensubtitles)) History.logSubtitle(episode.show.indexerid, episode.season, episode.episode, episode.status, subtitle) return current_subtitles, new_subtitles
def get(self, *args, **kwargs): limit = self.get_argument('limit', None) if limit is None: if sickrage.app.config.history_limit: limit = int(sickrage.app.config.history_limit) else: limit = 100 else: limit = int(limit) if sickrage.app.config.history_limit != limit: sickrage.app.config.history_limit = limit sickrage.app.config.save() compact = [] for row in History().get(limit): action = { 'action': row['action'], 'provider': row['provider'], 'release_group': row['release_group'], 'resource': row['resource'], 'time': row['date'] } if not any( (history['show_id'] == row['show_id'] and history['season'] == row['season'] and history['episode'] == row['episode'] and history['quality'] == row['quality']) for history in compact): history = { 'actions': [action], 'quality': row['quality'], 'resource': row['resource'], 'season': row['season'], 'episode': row['episode'], 'show_id': row['show_id'], 'show_name': row['show_name'] } compact.append(history) else: index = [ i for i, item in enumerate(compact) if item['show_id'] == row['show_id'] and item['season'] == row['season'] and item['episode'] == row['episode'] and item['quality'] == row['quality'] ][0] history = compact[index] history['actions'].append(action) history['actions'].sort(key=lambda d: d['time'], reverse=True) submenu = [ { 'title': _('Clear History'), 'path': '/history/clear', 'icon': 'fas fa-trash', 'class': 'clearhistory', 'confirm': True }, { 'title': _('Trim History'), 'path': '/history/trim', 'icon': 'fas fa-cut', 'class': 'trimhistory', 'confirm': True }, ] return self.render("/history.mako", historyResults=History().get(limit), compactResults=compact, limit=limit, submenu=submenu, title=_('History'), header=_('History'), topmenu="history", controller='root', action='history')
async def get(self, *args, **kwargs): await self.run_task(History().trim) sickrage.app.alerts.message( _('Removed history entries older than 30 days')) return self.redirect("/history/")
async def get(self, *args, **kwargs): await self.run_task(History().clear) sickrage.app.alerts.message(_('History cleared')) return self.redirect("/history/")
def snatchEpisode(result, endStatus=SNATCHED): """ Contains the internal logic necessary to actually "snatch" a result that has been found. :param result: SearchResult instance to be snatched. :param endStatus: the episode status that should be used for the episode object once it's snatched. :return: boolean, True on success """ if result is None: return False result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickrage.ALLOW_HIGH_PRIORITY: # if it aired recently make it high priority for curEp in result.episodes: if datetime.date.today() - curEp.airdate <= datetime.timedelta(days=7): result.priority = 1 if re.search(r"(^|[\. _-])(proper|repack)([\. _-]|$)", result.name, re.I) is not None: endStatus = SNATCHED_PROPER if result.url.startswith("magnet") or result.url.endswith("torrent"): result.resultType = "torrent" # NZBs can be sent straight to SAB or saved to disk if result.resultType in ("nzb", "nzbdata"): if sickrage.NZB_METHOD == "blackhole": dlResult = _downloadResult(result) elif sickrage.NZB_METHOD == "sabnzbd": dlResult = SabNZBd.sendNZB(result) elif sickrage.NZB_METHOD == "nzbget": is_proper = True if endStatus == SNATCHED_PROPER else False dlResult = NZBGet.sendNZB(result, is_proper) else: sickrage.LOGGER.error("Unknown NZB action specified in config: " + sickrage.NZB_METHOD) dlResult = False # TORRENTs can be sent to clients or saved to disk elif result.resultType == "torrent": # torrents are saved to disk when blackhole mode if sickrage.TORRENT_METHOD == "blackhole": dlResult = _downloadResult(result) else: if not result.content and not result.url.startswith("magnet"): result.content = result.provider.getURL(result.url, needBytes=True) if result.content or result.url.startswith("magnet"): client = getClientIstance(sickrage.TORRENT_METHOD)() dlResult = client.sendTORRENT(result) else: sickrage.LOGGER.warning("Torrent file content is empty") dlResult = False else: sickrage.LOGGER.error("Unknown result type, unable to download it (%r)" % result.resultType) dlResult = False if not dlResult: return False if sickrage.USE_FAILED_DOWNLOADS: FailedHistory.logSnatch(result) notifications.message("Episode snatched", result.name) History.logSnatch(result) # don't notify when we re-download an episode sql_l = [] trakt_data = [] for curEpObj in result.episodes: with curEpObj.lock: if isFirstBestMatch(result): curEpObj.status = Quality.compositeStatus(SNATCHED_BEST, result.quality) else: curEpObj.status = Quality.compositeStatus(endStatus, result.quality) sql_l.append(curEpObj.get_sql()) if curEpObj.status not in Quality.DOWNLOADED: try: notify_snatch(curEpObj._format_pattern("%SN - %Sx%0E - %EN - %QN") + " from " + result.provider.name) except: sickrage.LOGGER.debug("Failed to send snatch notification") trakt_data.append((curEpObj.season, curEpObj.episode)) data = sickrage.NOTIFIERS.trakt_notifier.trakt_episode_data_generate(trakt_data) if sickrage.USE_TRAKT and sickrage.TRAKT_SYNC_WATCHLIST: sickrage.LOGGER.debug( "Add episodes, showid: indexerid " + str(result.show.indexerid) + ", Title " + str(result.show.name) + " to Traktv Watchlist" ) if data: sickrage.NOTIFIERS.trakt_notifier.update_watchlist(result.show, data_episode=data, update="add") if len(sql_l) > 0: main_db.MainDB().mass_action(sql_l) return True
def snatchEpisode(result, endStatus=SNATCHED): """ Contains the internal logic necessary to actually "snatch" a result that has been found. :param result: SearchResult instance to be snatched. :param endStatus: the episode status that should be used for the episode object once it's snatched. :return: boolean, True on success """ if result is None: return False result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickrage.app.config.allow_high_priority: # if it aired recently make it high priority for curEp in result.episodes: if date.today() - curEp.airdate <= timedelta(days=7): result.priority = 1 if re.search(r'(^|[. _-])(proper|repack)([. _-]|$)', result.name, re.I) is not None: endStatus = SNATCHED_PROPER # get result content result.content = result.provider.get_content(result.url) dlResult = False if result.resultType in ("nzb", "nzbdata"): if sickrage.app.config.nzb_method == "blackhole": dlResult = result.provider.download_result(result) elif sickrage.app.config.nzb_method == "sabnzbd": dlResult = SabNZBd.sendNZB(result) elif sickrage.app.config.nzb_method == "nzbget": is_proper = True if endStatus == SNATCHED_PROPER else False dlResult = NZBGet.sendNZB(result, is_proper) else: sickrage.app.log.error("Unknown NZB action specified in config: " + sickrage.app.config.nzb_method) elif result.resultType in ("torrent", "torznab"): # add public trackers to torrent result if not result.provider.private: result = result.provider.add_trackers(result) if sickrage.app.config.torrent_method == "blackhole": dlResult = result.provider.download_result(result) else: if any([result.content, result.url.startswith('magnet:')]): client = getClientIstance(sickrage.app.config.torrent_method)() dlResult = client.send_torrent(result) else: sickrage.app.log.warning("Torrent file content is empty") else: sickrage.app.log.error( "Unknown result type, unable to download it (%r)" % result.resultType) # no download results found if not dlResult: return False FailedHistory.logSnatch(result) sickrage.app.alerts.message(_('Episode snatched'), result.name) History.logSnatch(result) # don't notify when we re-download an episode trakt_data = [] for curEpObj in result.episodes: with curEpObj.lock: if isFirstBestMatch(result): curEpObj.status = Quality.compositeStatus( SNATCHED_BEST, result.quality) else: curEpObj.status = Quality.compositeStatus( endStatus, result.quality) # save episode to DB curEpObj.save_to_db() if curEpObj.status not in Quality.DOWNLOADED: try: Notifiers.mass_notify_snatch( curEpObj._format_pattern('%SN - %Sx%0E - %EN - %QN') + " from " + result.provider.name) except: sickrage.app.log.debug("Failed to send snatch notification") trakt_data.append((curEpObj.season, curEpObj.episode)) data = sickrage.app.notifier_providers[ 'trakt'].trakt_episode_data_generate(trakt_data) if sickrage.app.config.use_trakt and sickrage.app.config.trakt_sync_watchlist: sickrage.app.log.debug("Add episodes, showid: indexerid " + str(result.show.indexerid) + ", Title " + str(result.show.name) + " to Traktv Watchlist") if data: sickrage.app.notifier_providers['trakt'].update_watchlist( result.show, data_episode=data, update="add") return True
def snatchEpisode(result, endStatus=SNATCHED): """ Contains the internal logic necessary to actually "snatch" a result that has been found. :param result: SearchResult instance to be snatched. :param endStatus: the episode status that should be used for the episode object once it's snatched. :return: boolean, True on success """ if result is None: return False result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickrage.srCore.srConfig.ALLOW_HIGH_PRIORITY: # if it aired recently make it high priority for curEp in result.episodes: if date.today() - curEp.airdate <= timedelta(days=7): result.priority = 1 if re.search(r'(^|[\. _-])(proper|repack)([\. _-]|$)', result.name, re.I) is not None: endStatus = SNATCHED_PROPER if result.url.startswith('magnet') or result.url.endswith('torrent'): result.resultType = 'torrent' dlResult = False if result.resultType in ("nzb", "nzbdata"): if sickrage.srCore.srConfig.NZB_METHOD == "blackhole": dlResult = _downloadResult(result) elif sickrage.srCore.srConfig.NZB_METHOD == "sabnzbd": dlResult = SabNZBd.sendNZB(result) elif sickrage.srCore.srConfig.NZB_METHOD == "nzbget": is_proper = True if endStatus == SNATCHED_PROPER else False dlResult = NZBGet.sendNZB(result, is_proper) else: sickrage.srCore.srLogger.error( "Unknown NZB action specified in config: " + sickrage.srCore.srConfig.NZB_METHOD) elif result.resultType == "torrent": if sickrage.srCore.srConfig.TORRENT_METHOD == "blackhole": dlResult = _downloadResult(result) else: if all([not result.content, not result.url.startswith('magnet:')]): result.content = sickrage.srCore.srWebSession.get(result.url).content if any([result.content, result.url.startswith('magnet:')]): # add public trackers to magnet url for non-private torrent providers if not result.provider.private and result.url.startswith('magnet:'): result.url += '&tr='.join( [x.strip() for x in sickrage.srCore.srConfig.TORRENT_TRACKERS.split(',') if x.strip()]) client = getClientIstance(sickrage.srCore.srConfig.TORRENT_METHOD)() dlResult = client.sendTORRENT(result) else: sickrage.srCore.srLogger.warning("Torrent file content is empty") else: sickrage.srCore.srLogger.error("Unknown result type, unable to download it (%r)" % result.resultType) # no download results found if not dlResult: return False if sickrage.srCore.srConfig.USE_FAILED_DOWNLOADS: FailedHistory.logSnatch(result) sickrage.srCore.srNotifications.message('Episode snatched', result.name) History.logSnatch(result) # don't notify when we re-download an episode trakt_data = [] for curEpObj in result.episodes: with curEpObj.lock: if isFirstBestMatch(result): curEpObj.status = Quality.compositeStatus(SNATCHED_BEST, result.quality) else: curEpObj.status = Quality.compositeStatus(endStatus, result.quality) # save episode to DB curEpObj.saveToDB() if curEpObj.status not in Quality.DOWNLOADED: try: srNotifiers.notify_snatch( curEpObj._format_pattern('%SN - %Sx%0E - %EN - %QN') + " from " + result.provider.name) except: sickrage.srCore.srLogger.debug("Failed to send snatch notification") trakt_data.append((curEpObj.season, curEpObj.episode)) data = sickrage.srCore.notifiersDict['trakt'].trakt_episode_data_generate(trakt_data) if sickrage.srCore.srConfig.USE_TRAKT and sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST: sickrage.srCore.srLogger.debug( "Add episodes, showid: indexerid " + str(result.show.indexerid) + ", Title " + str( result.show.name) + " to Traktv Watchlist") if data: sickrage.srCore.notifiersDict['trakt'].update_watchlist(result.show, data_episode=data, update="add") return True
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 + "]")
def snatchEpisode(result, endStatus=SNATCHED): """ Contains the internal logic necessary to actually "snatch" a result that has been found. :param result: SearchResult instance to be snatched. :param endStatus: the episode status that should be used for the episode object once it's snatched. :return: boolean, True on success """ if result is None: return False result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickrage.app.config.allow_high_priority: # if it aired recently make it high priority for curEp in result.episodes: if date.today() - curEp.airdate <= timedelta(days=7): result.priority = 1 if re.search(r'(^|[. _-])(proper|repack)([. _-]|$)', result.name, re.I) is not None: endStatus = SNATCHED_PROPER # get result content result.content = result.provider.get_content(result.url) dlResult = False if result.resultType in ("nzb", "nzbdata"): if sickrage.app.config.nzb_method == "blackhole": dlResult = result.provider.download_result(result) elif sickrage.app.config.nzb_method == "sabnzbd": dlResult = SabNZBd.sendNZB(result) elif sickrage.app.config.nzb_method == "nzbget": is_proper = True if endStatus == SNATCHED_PROPER else False dlResult = NZBGet.sendNZB(result, is_proper) else: sickrage.app.log.error("Unknown NZB action specified in config: " + sickrage.app.config.nzb_method) elif result.resultType in ("torrent", "torznab"): # add public trackers to torrent result if not result.provider.private: result = result.provider.add_trackers(result) if sickrage.app.config.torrent_method == "blackhole": dlResult = result.provider.download_result(result) else: if any([result.content, result.url.startswith('magnet:')]): client = getClientIstance(sickrage.app.config.torrent_method)() dlResult = client.send_torrent(result) else: sickrage.app.log.warning("Torrent file content is empty") else: sickrage.app.log.error("Unknown result type, unable to download it (%r)" % result.resultType) # no download results found if not dlResult: return False FailedHistory.logSnatch(result) sickrage.app.alerts.message(_('Episode snatched'), result.name) History.logSnatch(result) # don't notify when we re-download an episode trakt_data = [] for curEpObj in result.episodes: with curEpObj.lock: if isFirstBestMatch(result): curEpObj.status = Quality.compositeStatus(SNATCHED_BEST, result.quality) else: curEpObj.status = Quality.compositeStatus(endStatus, result.quality) # save episode to DB curEpObj.save_to_db() if curEpObj.status not in Quality.DOWNLOADED: try: Notifiers.mass_notify_snatch( curEpObj._format_pattern('%SN - %Sx%0E - %EN - %QN') + " from " + result.provider.name) except: sickrage.app.log.debug("Failed to send snatch notification") trakt_data.append((curEpObj.season, curEpObj.episode)) data = sickrage.app.notifier_providers['trakt'].trakt_episode_data_generate(trakt_data) if sickrage.app.config.use_trakt and sickrage.app.config.trakt_sync_watchlist: sickrage.app.log.debug( "Add episodes, showid: indexerid " + str(result.show.indexerid) + ", Title " + str( result.show.name) + " to Traktv Watchlist") if data: sickrage.app.notifier_providers['trakt'].update_watchlist(result.show, data_episode=data, update="add") return True
def handle_get(self): History().trim() sickrage.app.alerts.message( _('Removed history entries older than 30 days')) return self.redirect("/history/")
def handle_get(self): History().clear() sickrage.app.alerts.message(_('History cleared')) return self.redirect("/history/")
def download_subtitles(episode): existing_subtitles = episode.subtitles # First of all, check if we need subtitles languages = get_needed_languages(existing_subtitles) if not languages: sickrage.srCore.srLogger.debug('%s: No missing subtitles for S%02dE%02d' % ( episode.show.indexerid, episode.season, episode.episode)) return existing_subtitles, None subtitles_path = get_subtitles_path(episode.location) video_path = episode.location providers = getEnabledServiceList() video = get_video(video_path, subtitles_path=subtitles_path, episode=episode) if not video: sickrage.srCore.srLogger.debug('%s: Exception caught in subliminal.scan_video for S%02dE%02d' % (episode.show.indexerid, episode.season, episode.episode)) return existing_subtitles, None provider_configs = { 'addic7ed': {'username': sickrage.srCore.srConfig.ADDIC7ED_USER, 'password': sickrage.srCore.srConfig.ADDIC7ED_PASS}, 'itasa': {'username': sickrage.srCore.srConfig.ITASA_USER, 'password': sickrage.srCore.srConfig.ITASA_PASS}, 'legendastv': {'username': sickrage.srCore.srConfig.LEGENDASTV_USER, 'password': sickrage.srCore.srConfig.LEGENDASTV_PASS}, 'opensubtitles': {'username': sickrage.srCore.srConfig.OPENSUBTITLES_USER, 'password': sickrage.srCore.srConfig.OPENSUBTITLES_PASS}} pool = subliminal.ProviderPool(providers=providers, provider_configs=provider_configs) try: subtitles_list = pool.list_subtitles(video, languages) if not subtitles_list: sickrage.srCore.srLogger.debug('%s: No subtitles found for S%02dE%02d on any provider' % ( episode.show.indexerid, episode.season, episode.episode)) return existing_subtitles, None found_subtitles = pool.download_best_subtitles(subtitles_list, video, languages=languages, hearing_impaired=sickrage.srCore.srConfig.SUBTITLES_HEARING_IMPAIRED, only_one=not sickrage.srCore.srConfig.SUBTITLES_MULTI) save_subtitles(video, found_subtitles, directory=subtitles_path, single=not sickrage.srCore.srConfig.SUBTITLES_MULTI) if not sickrage.srCore.srConfig.EMBEDDED_SUBTITLES_ALL and sickrage.srCore.srConfig.SUBTITLES_EXTRA_SCRIPTS and video_path.endswith( ('.mkv', '.mp4')): run_subs_extra_scripts(episode, found_subtitles, video, single=not sickrage.srCore.srConfig.SUBTITLES_MULTI) new_subtitles = sorted({subtitle.language.opensubtitles for subtitle in found_subtitles}) current_subtitles = sorted({subtitle for subtitle in new_subtitles + existing_subtitles if subtitle}) if not sickrage.srCore.srConfig.SUBTITLES_MULTI and len(found_subtitles) == 1: new_code = found_subtitles[0].language.opensubtitles if new_code not in existing_subtitles: current_subtitles.remove(new_code) current_subtitles.append('und') except Exception: sickrage.srCore.srLogger.info("Error occurred when downloading subtitles for: %s" % video_path) sickrage.srCore.srLogger.error(traceback.format_exc()) return existing_subtitles, None if sickrage.srCore.srConfig.SUBTITLES_HISTORY: from sickrage.core.tv.show.history import History for subtitle in found_subtitles: sickrage.srCore.srLogger.debug( 'history.logSubtitle %s, %s' % (subtitle.provider_name, subtitle.language.opensubtitles)) History.logSubtitle(episode.show.indexerid, episode.season, episode.episode, episode.status, subtitle) return current_subtitles, new_subtitles
def snatchEpisode(result, endStatus=SNATCHED): """ Contains the internal logic necessary to actually "snatch" a result that has been found. :param result: SearchResult instance to be snatched. :param endStatus: the episode status that should be used for the episode object once it's snatched. :return: boolean, True on success """ if result is None: return False result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickrage.ALLOW_HIGH_PRIORITY: # if it aired recently make it high priority for curEp in result.episodes: if datetime.date.today() - curEp.airdate <= datetime.timedelta( days=7): result.priority = 1 if re.search(r'(^|[\. _-])(proper|repack)([\. _-]|$)', result.name, re.I) is not None: endStatus = SNATCHED_PROPER if result.url.startswith('magnet') or result.url.endswith('torrent'): result.resultType = 'torrent' # NZBs can be sent straight to SAB or saved to disk if result.resultType in ("nzb", "nzbdata"): if sickrage.NZB_METHOD == "blackhole": dlResult = _downloadResult(result) elif sickrage.NZB_METHOD == "sabnzbd": dlResult = SabNZBd.sendNZB(result) elif sickrage.NZB_METHOD == "nzbget": is_proper = True if endStatus == SNATCHED_PROPER else False dlResult = NZBGet.sendNZB(result, is_proper) else: sickrage.LOGGER.error("Unknown NZB action specified in config: " + sickrage.NZB_METHOD) dlResult = False # TORRENTs can be sent to clients or saved to disk elif result.resultType == "torrent": # torrents are saved to disk when blackhole mode if sickrage.TORRENT_METHOD == "blackhole": dlResult = _downloadResult(result) else: if not result.content and not result.url.startswith('magnet'): result.content = result.provider.getURL(result.url, needBytes=True) if result.content or result.url.startswith('magnet'): client = getClientIstance(sickrage.TORRENT_METHOD)() dlResult = client.sendTORRENT(result) else: sickrage.LOGGER.warning("Torrent file content is empty") dlResult = False else: sickrage.LOGGER.error( "Unknown result type, unable to download it (%r)" % result.resultType) dlResult = False if not dlResult: return False if sickrage.USE_FAILED_DOWNLOADS: FailedHistory.logSnatch(result) notifications.message('Episode snatched', result.name) History.logSnatch(result) # don't notify when we re-download an episode sql_l = [] trakt_data = [] for curEpObj in result.episodes: with curEpObj.lock: if isFirstBestMatch(result): curEpObj.status = Quality.compositeStatus( SNATCHED_BEST, result.quality) else: curEpObj.status = Quality.compositeStatus( endStatus, result.quality) sql_l.append(curEpObj.get_sql()) if curEpObj.status not in Quality.DOWNLOADED: try: notify_snatch( curEpObj._format_pattern('%SN - %Sx%0E - %EN - %QN') + " from " + result.provider.name) except: sickrage.LOGGER.debug("Failed to send snatch notification") trakt_data.append((curEpObj.season, curEpObj.episode)) data = sickrage.NOTIFIERS.trakt_notifier.trakt_episode_data_generate( trakt_data) if sickrage.USE_TRAKT and sickrage.TRAKT_SYNC_WATCHLIST: sickrage.LOGGER.debug("Add episodes, showid: indexerid " + str(result.show.indexerid) + ", Title " + str(result.show.name) + " to Traktv Watchlist") if data: sickrage.NOTIFIERS.trakt_notifier.update_watchlist( result.show, data_episode=data, update="add") if len(sql_l) > 0: main_db.MainDB().mass_action(sql_l) return True
def get(self, *args, **kwargs): History().clear() sickrage.app.alerts.message(_('History cleared')) return self.redirect("/history/")
def snatchEpisode(result, endStatus=SNATCHED): """ Contains the internal logic necessary to actually "snatch" a result that has been found. :param result: SearchResult instance to be snatched. :param endStatus: the episode status that should be used for the episode object once it's snatched. :return: boolean, True on success """ if result is None: return False result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickrage.srCore.srConfig.ALLOW_HIGH_PRIORITY: # if it aired recently make it high priority for curEp in result.episodes: if date.today() - curEp.airdate <= timedelta(days=7): result.priority = 1 if re.search(r'(^|[\. _-])(proper|repack)([\. _-]|$)', result.name, re.I) is not None: endStatus = SNATCHED_PROPER if result.url.startswith('magnet') or result.url.endswith('torrent'): result.resultType = 'torrent' dlResult = False if result.resultType in ("nzb", "nzbdata"): if sickrage.srCore.srConfig.NZB_METHOD == "blackhole": dlResult = _downloadResult(result) elif sickrage.srCore.srConfig.NZB_METHOD == "sabnzbd": dlResult = SabNZBd.sendNZB(result) elif sickrage.srCore.srConfig.NZB_METHOD == "nzbget": is_proper = True if endStatus == SNATCHED_PROPER else False dlResult = NZBGet.sendNZB(result, is_proper) else: sickrage.srCore.srLogger.error( "Unknown NZB action specified in config: " + sickrage.srCore.srConfig.NZB_METHOD) elif result.resultType == "torrent": if sickrage.srCore.srConfig.TORRENT_METHOD == "blackhole": dlResult = _downloadResult(result) else: if all([not result.content, not result.url.startswith('magnet:')]): result.content = sickrage.srCore.srWebSession.get(result.url).content if any([result.content, result.url.startswith('magnet:')]): # add public trackers to magnet url for non-private torrent providers if not result.provider.private and result.url.startswith('magnet:'): result.url += '&tr='.join( [x.strip() for x in sickrage.srCore.srConfig.TORRENT_TRACKERS.split(',') if x.strip()]) client = getClientIstance(sickrage.srCore.srConfig.TORRENT_METHOD)() dlResult = client.sendTORRENT(result) else: sickrage.srCore.srLogger.warning("Torrent file content is empty") else: sickrage.srCore.srLogger.error("Unknown result type, unable to download it (%r)" % result.resultType) # no download results found if not dlResult: return False if sickrage.srCore.srConfig.USE_FAILED_DOWNLOADS: FailedHistory.logSnatch(result) sickrage.srCore.srNotifications.message('Episode snatched', result.name) History.logSnatch(result) # don't notify when we re-download an episode sql_l = [] trakt_data = [] for curEpObj in result.episodes: with curEpObj.lock: if isFirstBestMatch(result): curEpObj.status = Quality.compositeStatus(SNATCHED_BEST, result.quality) else: curEpObj.status = Quality.compositeStatus(endStatus, result.quality) sql_q = curEpObj.saveToDB(False) if sql_q: sql_l.append(sql_q) if curEpObj.status not in Quality.DOWNLOADED: try: srNotifiers.notify_snatch( curEpObj._format_pattern('%SN - %Sx%0E - %EN - %QN') + " from " + result.provider.name) except: sickrage.srCore.srLogger.debug("Failed to send snatch notification") trakt_data.append((curEpObj.season, curEpObj.episode)) data = sickrage.srCore.notifiersDict.trakt_notifier.trakt_episode_data_generate(trakt_data) if sickrage.srCore.srConfig.USE_TRAKT and sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST: sickrage.srCore.srLogger.debug( "Add episodes, showid: indexerid " + str(result.show.indexerid) + ", Title " + str( result.show.name) + " to Traktv Watchlist") if data: sickrage.srCore.notifiersDict.trakt_notifier.update_watchlist(result.show, data_episode=data, update="add") if len(sql_l) > 0: main_db.MainDB().mass_upsert(sql_l) del sql_l # cleanup return True
def download_subtitles(self, show_id, season, episode, session=None): show_object = find_show(show_id, session=session) episode_object = show_object.get_episode(season, episode) existing_subtitles = episode_object.subtitles if not isinstance(existing_subtitles, list): existing_subtitles = [] # First of all, check if we need subtitles languages = self.get_needed_languages(existing_subtitles) if not languages: sickrage.app.log.debug('%s: No missing subtitles for S%02dE%02d' % (show_id, season, episode)) return existing_subtitles, None subtitles_path = self.get_subtitles_path(episode_object.location) video_path = episode_object.location providers = self.getEnabledServiceList() video = self.get_video(video_path, subtitles_path=subtitles_path, episode_object=episode_object) if not video: sickrage.app.log.debug( '%s: Exception caught in subliminal.scan_video for S%02dE%02d' % (show_id, season, episode)) return existing_subtitles, None provider_configs = { 'addic7ed': { 'username': sickrage.app.config.addic7ed_user, 'password': sickrage.app.config.addic7ed_pass }, 'itasa': { 'username': sickrage.app.config.itasa_user, 'password': sickrage.app.config.itasa_pass }, 'legendastv': { 'username': sickrage.app.config.legendastv_user, 'password': sickrage.app.config.legendastv_pass }, 'opensubtitles': { 'username': sickrage.app.config.opensubtitles_user, 'password': sickrage.app.config.opensubtitles_pass } } pool = subliminal.ProviderPool(providers=providers, provider_configs=provider_configs) try: subtitles_list = pool.list_subtitles(video, languages) if not subtitles_list: sickrage.app.log.debug( '%s: No subtitles found for S%02dE%02d on any provider' % (show_id, season, episode)) return existing_subtitles, None found_subtitles = pool.download_best_subtitles( subtitles_list, video, languages=languages, hearing_impaired=sickrage.app.config. subtitles_hearing_impaired, only_one=not sickrage.app.config.subtitles_multi) save_subtitles(video, found_subtitles, directory=subtitles_path, single=not sickrage.app.config.subtitles_multi) if not sickrage.app.config.embedded_subtitles_all and sickrage.app.config.subtitles_extra_scripts and video_path.endswith( ('.mkv', '.mp4')): self.run_subs_extra_scripts( episode_object, found_subtitles, video, single=not sickrage.app.config.subtitles_multi) new_subtitles = sorted({ subtitle.language.opensubtitles for subtitle in found_subtitles }) current_subtitles = sorted({ subtitle for subtitle in new_subtitles + existing_subtitles if subtitle }) if not sickrage.app.config.subtitles_multi and len( found_subtitles) == 1: new_code = found_subtitles[0].language.opensubtitles if new_code not in existing_subtitles: current_subtitles.remove(new_code) current_subtitles.append('und') except Exception as e: sickrage.app.log.error( "Error occurred when downloading subtitles for {}: {}".format( video_path, e)) return existing_subtitles, None if sickrage.app.config.subtitles_history: for subtitle in found_subtitles: sickrage.app.log.debug( 'history.logSubtitle %s, %s' % (subtitle.provider_name, subtitle.language.opensubtitles)) History.log_subtitle(show_id, season, episode, episode_object.status, subtitle) return current_subtitles, new_subtitles
def snatch_episode(result, end_status=EpisodeStatus.SNATCHED): """ Contains the internal logic necessary to actually "snatch" a result that has been found. :param result: SearchResult instance to be snatched. :param end_status: the episode status that should be used for the episode object once it's snatched. :return: boolean, True on success """ if result is None: return False show_object = find_show(result.series_id, result.series_provider_id) result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickrage.app.config.general.allow_high_priority: # if it aired recently make it high priority for episode_number in result.episodes: if date.today() - show_object.get_episode(result.season, episode_number).airdate <= timedelta(days=7): result.priority = 1 if re.search(r'(^|[. _-])(proper|repack)([. _-]|$)', result.name, re.I) is not None: end_status = EpisodeStatus.SNATCHED_PROPER # get result content result.content = result.provider.get_content(result.url) dlResult = False if result.provider_type in (SearchProviderType.NZB, SearchProviderType.NZBDATA): if sickrage.app.config.general.nzb_method == NzbMethod.BLACKHOLE: dlResult = result.provider.download_result(result) elif sickrage.app.config.general.nzb_method == NzbMethod.SABNZBD: dlResult = SabNZBd.sendNZB(result) elif sickrage.app.config.general.nzb_method == NzbMethod.NZBGET: is_proper = True if end_status == EpisodeStatus.SNATCHED_PROPER else False dlResult = NZBGet.sendNZB(result, is_proper) elif sickrage.app.config.general.nzb_method == NzbMethod.DOWNLOAD_STATION: client = get_client_instance(sickrage.app.config.general.nzb_method.value, client_type='nzb')() dlResult = client.sendNZB(result) elif result.provider_type in (SearchProviderType.TORRENT, SearchProviderType.TORZNAB): # add public trackers to torrent result if not result.provider.private: result = result.provider.add_trackers(result) if sickrage.app.config.general.torrent_method == TorrentMethod.BLACKHOLE: dlResult = result.provider.download_result(result) else: if any([result.content, result.url.startswith('magnet:')]): client = get_client_instance(sickrage.app.config.general.torrent_method.value, client_type='torrent')() dlResult = client.send_torrent(result) else: sickrage.app.log.warning("Torrent file content is empty") else: sickrage.app.log.error("Unknown result type, unable to download it (%r)" % result.provider_type.display_name) # no download results found if not dlResult: return False FailedHistory.log_snatch(result) History.log_snatch(result) sickrage.app.alerts.message(_('Episode snatched'), result.name) trakt_data = [] for episode_number in result.episodes: episode_obj = show_object.get_episode(result.season, episode_number) if is_first_best_match(result): episode_obj.status = Quality.composite_status(EpisodeStatus.SNATCHED_BEST, result.quality) else: episode_obj.status = Quality.composite_status(end_status, result.quality) episode_obj.save() # don't notify when we re-download an episode if episode_obj.status not in EpisodeStatus.composites(EpisodeStatus.DOWNLOADED): try: NotificationProvider.mass_notify_snatch(episode_obj._format_pattern('%SN - %Sx%0E - %EN - %QN') + " from " + result.provider.name) except Exception: sickrage.app.log.debug("Failed to send snatch notification") trakt_data.append((episode_obj.season, episode_obj.episode)) data = sickrage.app.notification_providers['trakt'].trakt_episode_data_generate(trakt_data) if sickrage.app.config.trakt.enable and sickrage.app.config.trakt.sync_watchlist: if data: sickrage.app.notification_providers['trakt'].update_watchlist(show_object, data_episode=data, update="add") return True