Beispiel #1
0
def wantedEpisodes(show, fromDate):
    """
    Get a list of episodes that we want to download
    :param show: Show these episodes are from
    :param fromDate: Search from a certain date
    :return: list of wanted episodes
    """

    wanted = []
    anyQualities, bestQualities = Quality.splitQuality(show.quality)  # @UnusedVariable
    allQualities = list(set(anyQualities + bestQualities))

    sickrage.srCore.srLogger.debug("Seeing if we need anything from {}".format(show.name))

    # check through the list of statuses to see if we want any
    for dbData in [x['doc'] for x in sickrage.srCore.mainDB.db.get_many('tv_episodes', show.indexerid, with_doc=True)
                   if x['doc']['season'] > 0 and x['doc']['airdate'] > fromDate.toordinal()]:

        curCompositeStatus = int(dbData["status"] or -1)
        curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus)

        if bestQualities:
            highestBestQuality = max(allQualities)
        else:
            highestBestQuality = 0

        # if we need a better one then say yes
        if (curStatus in (DOWNLOADED, SNATCHED,
                          SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED:
            epObj = show.getEpisode(int(dbData["season"]), int(dbData["episode"]))
            epObj.wantedQuality = [i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN)]
            wanted.append(epObj)

    return wanted
Beispiel #2
0
def refine_video(video, episode):
    # try to enrich video object using information in original filename
    if episode.release_name:
        guess_ep = subliminal.Episode.fromguess(None, guessit(episode.release_name))
        for name in vars(guess_ep):
            if getattr(guess_ep, name) and not getattr(video, name):
                setattr(video, name, getattr(guess_ep, name))

    # Use sickrage metadata
    metadata_mapping = {
        'episode': 'episode',
        'release_group': 'release_group',
        'season': 'season',
        'series': 'show.name',
        'series_imdb_id': 'show.imdbid',
        'size': 'file_size',
        'title': 'name',
        'year': 'show.startyear'
    }

    def get_attr_value(obj, name):
        value = None
        for attr in name.split('.'):
            if not value:
                value = getattr(obj, attr, None)
            else:
                value = getattr(value, attr, None)

        return value

    for name in metadata_mapping:
        if not getattr(video, name) and get_attr_value(episode, metadata_mapping[name]):
            setattr(video, name, get_attr_value(episode, metadata_mapping[name]))
        elif episode.show.subtitles_sr_metadata and get_attr_value(episode, metadata_mapping[name]):
            setattr(video, name, get_attr_value(episode, metadata_mapping[name]))

    # Set quality from metadata
    _, quality = Quality.splitCompositeStatus(episode.status)
    if not video.format or episode.show.subtitles_sr_metadata:
        if quality & Quality.ANYHDTV:
            video.format = Quality.combinedQualityStrings.get(Quality.ANYHDTV)
        elif quality & Quality.ANYWEBDL:
            video.format = Quality.combinedQualityStrings.get(Quality.ANYWEBDL)
        elif quality & Quality.ANYBLURAY:
            video.format = Quality.combinedQualityStrings.get(Quality.ANYBLURAY)

    if not video.resolution or episode.show.subtitles_sr_metadata:
        if quality & (Quality.HDTV | Quality.HDWEBDL | Quality.HDBLURAY):
            video.resolution = '720p'
        elif quality & Quality.RAWHDTV:
            video.resolution = '1080i'
        elif quality & (Quality.FULLHDTV | Quality.FULLHDWEBDL | Quality.FULLHDBLURAY):
            video.resolution = '1080p'
        elif quality & (Quality.UHD_4K_TV | Quality.UHD_4K_WEBDL | Quality.UHD_4K_BLURAY):
            video.resolution = '4K'
        elif quality & (Quality.UHD_8K_TV | Quality.UHD_8K_WEBDL | Quality.UHD_8K_BLURAY):
            video.resolution = '8K'
Beispiel #3
0
    def _get_segments(show, fromDate):
        """
        Get a list of episodes that we want to download
        :param show: Show these episodes are from
        :param fromDate: Search from a certain date
        :return: list of wanted episodes
        """

        wanted = []

        anyQualities, bestQualities = Quality.splitQuality(show.quality)
        allQualities = list(set(anyQualities + bestQualities))

        sickrage.app.log.debug("Seeing if we need anything from {}".format(
            show.name))

        # check through the list of statuses to see if we want any
        for dbData in sickrage.app.main_db.get_many('tv_episodes',
                                                    show.indexerid):
            if dbData['season'] > 0 and dbData[
                    'airdate'] >= fromDate.toordinal():
                curStatus, curQuality = Quality.splitCompositeStatus(
                    int(dbData["status"] or -1))

                # if we need a better one then say yes
                if curStatus not in (WANTED, DOWNLOADED, SNATCHED,
                                     SNATCHED_PROPER):
                    continue

                if curStatus != WANTED:
                    if bestQualities:
                        if curQuality in bestQualities:
                            continue
                        elif curQuality != Quality.UNKNOWN and curQuality > max(
                                bestQualities):
                            continue
                    else:
                        if curQuality in anyQualities:
                            continue
                        elif curQuality != Quality.UNKNOWN and curQuality > max(
                                anyQualities):
                            continue

                # skip upgrading quality of downloaded episodes if enabled
                if curStatus == DOWNLOADED and show.skip_downloaded:
                    continue

                epObj = show.getEpisode(int(dbData["season"]),
                                        int(dbData["episode"]))
                epObj.wantedQuality = [
                    i for i in allQualities
                    if (i > curQuality and i != Quality.UNKNOWN)
                ]
                wanted.append(epObj)

        return wanted
Beispiel #4
0
    def process(self):
        """
        Do the actual work

        :return: True
        """
        self._log("Failed download detected: (" + str(self.nzb_name) + ", " +
                  str(self.dir_name) + ")")

        release_name = show_names.determineReleaseName(self.dir_name,
                                                       self.nzb_name)
        if release_name is None:
            self._log("Warning: unable to find a valid release name.",
                      sickrage.app.log.WARNING)
            raise FailedPostProcessingFailedException()

        try:
            parsed = NameParser(False).parse(release_name)
        except InvalidNameException:
            self._log("Error: release name is invalid: " + release_name,
                      sickrage.app.log.DEBUG)
            raise FailedPostProcessingFailedException()
        except InvalidShowException:
            self._log(
                "Error: unable to parse release name " + release_name +
                " into a valid show", sickrage.app.log.DEBUG)
            raise FailedPostProcessingFailedException()

        if parsed.show.paused:
            self._log(
                "Warning: skipping failed processing for {} because the show is paused"
                .format(release_name), sickrage.app.log.DEBUG)
            raise FailedPostProcessingFailedException()

        sickrage.app.log.debug("name_parser info: ")
        sickrage.app.log.debug(" - " + str(parsed.series_name))
        sickrage.app.log.debug(" - " + str(parsed.season_number))
        sickrage.app.log.debug(" - " + str(parsed.episode_numbers))
        sickrage.app.log.debug(" - " + str(parsed.extra_info))
        sickrage.app.log.debug(" - " + str(parsed.release_group))
        sickrage.app.log.debug(" - " + str(parsed.air_date))

        for episode in parsed.episode_numbers:
            segment = parsed.show.getEpisode(parsed.season_number, episode)

            curStatus, curQuality = Quality.splitCompositeStatus(
                segment.status)
            if curStatus not in {SNATCHED, SNATCHED_BEST, SNATCHED_PROPER}:
                continue

            sickrage.app.search_queue.put(
                FailedQueueItem(parsed.show, [segment]))

        return True
    def run(self, force=False):
        """
        Runs the failed searcher, queuing selected episodes for search that have failed to snatch
        :param force: Force search
        """
        if self.amActive or (not sickrage.app.config.use_failed_snatcher or sickrage.app.developer) and not force:
            return

        self.amActive = True

        # set thread name
        threading.currentThread().setName(self.name)

        # trim failed download history
        FailedHistory.trimHistory()

        sickrage.app.log.info("Searching for failed snatches")

        show = None
        failed_snatches = False

        snatched_episodes = (x for x in sickrage.app.main_db.all('history')
                             if x['action'] in Quality.SNATCHED + Quality.SNATCHED_BEST + Quality.SNATCHED_PROPER
                             and 24 >= int((datetime.datetime.now() - datetime.datetime.strptime(x['date'],
                                                                                                 History.date_format)).total_seconds() / 3600) >= sickrage.app.config.failed_snatch_age)

        downloaded_releases = ((x['showid'], x['season'], x['episode']) for x in
                               sickrage.app.main_db.all('history')
                               if x['action'] in Quality.DOWNLOADED)

        episodes = [x for x in snatched_episodes if (x['showid'], x['season'], x['episode']) not in downloaded_releases]

        for episode in episodes:
            failed_snatches = True
            if not show or int(episode["showid"]) != show.indexerid:
                show = findCertainShow(int(episode["showid"]))

            # for when there is orphaned series in the database but not loaded into our showlist
            if not show or show.paused:
                continue

            ep_obj = show.get_episode(int(episode['season']), int(episode['episode']))
            if isinstance(ep_obj, TVEpisode):
                curStatus, curQuality = Quality.splitCompositeStatus(ep_obj.status)
                if curStatus not in {SNATCHED, SNATCHED_BEST, SNATCHED_PROPER}:
                    continue

                # put it on the queue
                sickrage.app.search_queue.put(FailedQueueItem(show, [ep_obj], True))

        if not failed_snatches:
            sickrage.app.log.info("No failed snatches found")

        self.amActive = False
Beispiel #6
0
    def logFailed(epObj, release, provider=None):
        """
        Log a failed download

        :param epObj: Episode object
        :param release: Release group
        :param provider: Provider used for snatch
        """
        showid = int(epObj.show.indexerid)
        season = int(epObj.season)
        epNum = int(epObj.episode)
        status, quality = Quality.splitCompositeStatus(epObj.status)
        action = Quality.compositeStatus(FAILED, quality)

        History._logHistoryItem(action, showid, season, epNum, quality, release, provider)
Beispiel #7
0
    def _get_segments(self, show, fromDate):
        if show.paused:
            sickrage.srCore.srLogger.debug(
                "Skipping backlog for {show_name} because the show is paused".
                format(show_name=show.name))
            return {}

        anyQualities, bestQualities = Quality.splitQuality(
            show.quality)  # @UnusedVariable

        sickrage.srCore.srLogger.debug(
            "Seeing if we need anything from {}".format(show.name))

        # check through the list of statuses to see if we want any
        wanted = {}
        for result in [
                x['doc'] for x in sickrage.srCore.mainDB.db.get_many(
                    'tv_episodes', show.indexerid, with_doc=True)
                if x['doc']['season'] > 0
                and x['doc']['airdate'] > fromDate.toordinal()
        ]:
            curCompositeStatus = int(result["status"] or -1)
            curStatus, curQuality = Quality.splitCompositeStatus(
                curCompositeStatus)

            if bestQualities:
                highestBestQuality = max(bestQualities)
                lowestBestQuality = min(bestQualities)
            else:
                highestBestQuality = 0
                lowestBestQuality = 0

            # if we need a better one then say yes
            if (curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and
                    curQuality < highestBestQuality) or curStatus == WANTED:
                epObj = show.getEpisode(int(result["season"]),
                                        int(result["episode"]))

                # only fetch if not archive on first match, or if show is lowest than the lower expected quality
                if (epObj.show.archive_firstmatch == 0
                        or curQuality < lowestBestQuality):
                    if epObj.season not in wanted:
                        wanted[epObj.season] = [epObj]
                    else:
                        wanted[epObj.season].append(epObj)

        return wanted
Beispiel #8
0
def wantedEpisodes(show, fromDate):
    """
    Get a list of episodes that we want to download
    :param show: Show these episodes are from
    :param fromDate: Search from a certain date
    :return: list of wanted episodes
    """

    wanted = []
    anyQualities, bestQualities = Quality.splitQuality(
        show.quality)  # @UnusedVariable
    allQualities = list(set(anyQualities + bestQualities))

    sickrage.srCore.srLogger.debug("Seeing if we need anything from {}".format(
        show.name))

    sqlResults = main_db.MainDB().select(
        "SELECT status, season, episode FROM tv_episodes WHERE showid = ? AND season > 0 AND airdate > ?",
        [show.indexerid, fromDate.toordinal()])

    sickrage.srCore.srLogger.debug("Found {} episode(s) needed for {}".format(
        len(sqlResults), show.name))

    # check through the list of statuses to see if we want any
    for result in sqlResults:
        curCompositeStatus = int(result["status"] or -1)
        curStatus, curQuality = Quality.splitCompositeStatus(
            curCompositeStatus)

        if bestQualities:
            highestBestQuality = max(allQualities)
        else:
            highestBestQuality = 0

        # if we need a better one then say yes
        if (curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER)
                and curQuality < highestBestQuality) or curStatus == WANTED:
            epObj = show.getEpisode(int(result["season"]),
                                    int(result["episode"]))
            epObj.wantedQuality = [
                i for i in allQualities
                if (i > curQuality and i != Quality.UNKNOWN)
            ]
            wanted.append(epObj)

    return wanted
Beispiel #9
0
    def logSubtitle(showid, season, episode, status, subtitleResult):
        """
        Log download of subtitle

        :param showid: Showid of download
        :param season: Show season
        :param episode: Show episode
        :param status: Status of download
        :param subtitleResult: Result object
        """
        resource = subtitleResult.language.opensubtitles
        provider = subtitleResult.provider_name

        status, quality = Quality.splitCompositeStatus(status)
        action = Quality.compositeStatus(SUBTITLED, quality)

        History._logHistoryItem(action, showid, season, episode, quality, resource, provider)
Beispiel #10
0
    def _get_segments(self, show, from_date):
        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        sickrage.app.log.debug("Seeing if we need anything from {}".format(
            show.name))

        # check through the list of statuses to see if we want any
        wanted = []
        for result in (x for x in sickrage.app.main_db.get_many(
                'tv_episodes', show.indexerid)
                       if x['season'] > 0 and datetime.date.today().toordinal(
                       ) > x['airdate'] >= from_date.toordinal()):

            curStatus, curQuality = Quality.splitCompositeStatus(
                int(result["status"] or -1))

            # if we need a better one then say yes
            if curStatus not in {
                    WANTED, DOWNLOADED, SNATCHED, SNATCHED_PROPER
            }:
                continue

            if curStatus != WANTED:
                if bestQualities:
                    if curQuality in bestQualities:
                        continue
                    elif curQuality != Quality.UNKNOWN and curQuality > max(
                            bestQualities):
                        continue
                else:
                    if curQuality in anyQualities:
                        continue
                    elif curQuality != Quality.UNKNOWN and curQuality > max(
                            anyQualities):
                        continue

            # skip upgrading quality of downloaded episodes if enabled
            if curStatus == DOWNLOADED and show.skip_downloaded:
                continue

            epObj = show.getEpisode(int(result["season"]),
                                    int(result["episode"]))
            wanted.append(epObj)

        return wanted
Beispiel #11
0
    def _get_segments(show, fromDate):
        """
        Get a list of episodes that we want to download
        :param show: Show these episodes are from
        :param fromDate: Search from a certain date
        :return: list of wanted episodes
        """

        wanted = []

        anyQualities, bestQualities = Quality.splitQuality(show.quality)
        allQualities = list(set(anyQualities + bestQualities))

        sickrage.app.log.debug("Seeing if we need anything from {}".format(show.name))

        # check through the list of statuses to see if we want any
        for dbData in sickrage.app.main_db.get_many('tv_episodes', show.indexerid):
            if dbData['season'] > 0 and dbData['airdate'] >= fromDate.toordinal():
                curStatus, curQuality = Quality.splitCompositeStatus(int(dbData["status"] or -1))

                # if we need a better one then say yes
                if curStatus not in (WANTED, DOWNLOADED, SNATCHED, SNATCHED_PROPER):
                    continue

                if curStatus != WANTED:
                    if bestQualities:
                        if curQuality in bestQualities:
                            continue
                        elif curQuality != Quality.UNKNOWN and curQuality > max(bestQualities):
                            continue
                    else:
                        if curQuality in anyQualities:
                            continue
                        elif curQuality != Quality.UNKNOWN and curQuality > max(anyQualities):
                            continue

                # skip upgrading quality of downloaded episodes if enabled
                if curStatus == DOWNLOADED and show.skip_downloaded:
                    continue

                epObj = show.get_episode(int(dbData["season"]), int(dbData["episode"]))
                epObj.wantedQuality = [i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN)]
                wanted.append(epObj)

        return wanted
Beispiel #12
0
    def markFailed(epObj):
        """
        Mark an episode as failed

        :param epObj: Episode object to mark as failed
        :return: empty string
        """
        log_str = ""

        try:
            with epObj.lock:
                quality = Quality.splitCompositeStatus(epObj.status)[1]
                epObj.status = Quality.compositeStatus(FAILED, quality)
                epObj.saveToDB()

        except EpisodeNotFoundException as e:
            sickrage.srCore.srLogger.warning("Unable to get episode, please set its status manually: {}".format(e.message))

        return log_str
Beispiel #13
0
    def _get_segments(self, show, fromDate):
        if show.paused:
            sickrage.srCore.srLogger.debug("Skipping backlog for {show_name} because the show is paused".format(show_name=show.name))
            return {}

        anyQualities, bestQualities = Quality.splitQuality(show.quality)  # @UnusedVariable

        sickrage.srCore.srLogger.debug("Seeing if we need anything from {}".format(show.name))

        sqlResults = main_db.MainDB().select(
            "SELECT status, season, episode FROM tv_episodes WHERE season > 0 AND airdate > ? AND showid = ?",
            [fromDate.toordinal(), show.indexerid])

        # check through the list of statuses to see if we want any
        wanted = {}
        for result in sqlResults:
            curCompositeStatus = int(result["status"] or -1)
            curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus)

            if bestQualities:
                highestBestQuality = max(bestQualities)
                lowestBestQuality = min(bestQualities)
            else:
                highestBestQuality = 0
                lowestBestQuality = 0

            # if we need a better one then say yes
            if (curStatus in (DOWNLOADED, SNATCHED,
                              SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED:
                epObj = show.getEpisode(int(result["season"]), int(result["episode"]))

                # only fetch if not archive on first match, or if show is lowest than the lower expected quality
                if (epObj.show.archive_firstmatch == 0 or curQuality < lowestBestQuality):
                    if epObj.season not in wanted:
                        wanted[epObj.season] = [epObj]
                    else:
                        wanted[epObj.season].append(epObj)

        return wanted
Beispiel #14
0
    def _get_segments(self, show, fromDate):
        if show.paused:
            sickrage.LOGGER.debug("Skipping backlog for {show_name} because the show is paused".format(show_name=show.name))
            return {}

        anyQualities, bestQualities = Quality.splitQuality(show.quality)  # @UnusedVariable

        sickrage.LOGGER.debug("Seeing if we need anything from {show_name}".format(show_name=show.name))

        sqlResults = main_db.MainDB().select(
            "SELECT status, season, episode FROM tv_episodes WHERE season > 0 AND airdate > ? AND showid = ?",
            [fromDate.toordinal(), show.indexerid])

        # check through the list of statuses to see if we want any
        wanted = {}
        for result in sqlResults:
            curCompositeStatus = int(result[b"status"] or -1)
            curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus)

            if bestQualities:
                highestBestQuality = max(bestQualities)
                lowestBestQuality = min(bestQualities)
            else:
                highestBestQuality = 0
                lowestBestQuality = 0

            # if we need a better one then say yes
            if (curStatus in (DOWNLOADED, SNATCHED,
                              SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED:
                epObj = show.getEpisode(int(result[b"season"]), int(result[b"episode"]))

                # only fetch if not archive on first match, or if show is lowest than the lower expected quality
                if (epObj.show.archive_firstmatch == 0 or curQuality < lowestBestQuality):
                    if epObj.season not in wanted:
                        wanted[epObj.season] = [epObj]
                    else:
                        wanted[epObj.season].append(epObj)

        return wanted
Beispiel #15
0
def wantedEpisodes(show, fromDate):
    """
    Get a list of episodes that we want to download
    :param show: Show these episodes are from
    :param fromDate: Search from a certain date
    :return: list of wanted episodes
    """

    anyQualities, bestQualities = Quality.splitQuality(show.quality)  # @UnusedVariable
    allQualities = list(set(anyQualities + bestQualities))

    sickrage.LOGGER.debug("Seeing if we need anything from " + show.name)

    sqlResults = main_db.MainDB().select(
        "SELECT status, season, episode FROM tv_episodes WHERE showid = ? AND season > 0 AND airdate > ?",
        [show.indexerid, fromDate.toordinal()],
    )

    # check through the list of statuses to see if we want any
    wanted = []
    for result in sqlResults:
        curCompositeStatus = int(result[b"status"] or -1)
        curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus)

        if bestQualities:
            highestBestQuality = max(allQualities)
        else:
            highestBestQuality = 0

        # if we need a better one then say yes
        if (
            curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and curQuality < highestBestQuality
        ) or curStatus == WANTED:
            epObj = show.getEpisode(int(result[b"season"]), int(result[b"episode"]))
            epObj.wantedQuality = [i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN)]
            wanted.append(epObj)

    return wanted
Beispiel #16
0
def wantedEpisodes(show, fromDate):
    """
    Get a list of episodes that we want to download
    :param show: Show these episodes are from
    :param fromDate: Search from a certain date
    :return: list of wanted episodes
    """

    wanted = []
    if show.paused:
        sickrage.app.log.debug("Not checking for episodes of {} because the show is paused".format(show.name))
        return wanted

    anyQualities, bestQualities = Quality.splitQuality(show.quality)
    allQualities = list(set(anyQualities + bestQualities))

    sickrage.app.log.debug("Seeing if we need anything from {}".format(show.name))

    # check through the list of statuses to see if we want any
    for dbData in [x['doc'] for x in sickrage.app.main_db.db.get_many('tv_episodes', show.indexerid, with_doc=True)
                   if x['doc']['season'] > 0 and x['doc']['airdate'] > fromDate.toordinal()]:

        curCompositeStatus = int(dbData["status"] or -1)
        curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus)

        if bestQualities:
            highestBestQuality = max(allQualities)
        else:
            highestBestQuality = 0

        # if we need a better one then say yes
        if (curStatus in (DOWNLOADED, SNATCHED,
                          SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED:
            epObj = show.getEpisode(int(dbData["season"]), int(dbData["episode"]))
            epObj.wantedQuality = [i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN)]
            wanted.append(epObj)

    return wanted
Beispiel #17
0
    def _get_segments(self, show, fromDate):
        if show.paused:
            sickrage.app.log.debug(
                "Skipping backlog for {show_name} because the show is paused".format(show_name=show.name))
            return {}

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        sickrage.app.log.debug("Seeing if we need anything from {}".format(show.name))

        # check through the list of statuses to see if we want any
        wanted = {}
        for result in [x['doc'] for x in
                       sickrage.app.main_db.db.get_many('tv_episodes', show.indexerid, with_doc=True)
                       if x['doc']['season'] > 0 and x['doc']['airdate'] > fromDate.toordinal()]:
            curCompositeStatus = int(result["status"] or -1)
            curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus)

            if bestQualities:
                highestBestQuality = max(bestQualities)
                lowestBestQuality = min(bestQualities)
            else:
                highestBestQuality = 0
                lowestBestQuality = 0

            # if we need a better one then say yes
            if (curStatus in (DOWNLOADED, SNATCHED,
                              SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED:
                epObj = show.getEpisode(int(result["season"]), int(result["episode"]))

                # only fetch if not archive on first match, or if show is lowest than the lower expected quality
                if epObj.show.archive_firstmatch == 0 or curQuality < lowestBestQuality:
                    if epObj.season not in wanted:
                        wanted[epObj.season] = [epObj]
                    else:
                        wanted[epObj.season].append(epObj)

        return wanted
Beispiel #18
0
    def _get_segments(show, from_date):
        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        sickrage.app.log.debug("Seeing if we need anything from {}".format(show.name))

        # check through the list of statuses to see if we want any
        wanted = []
        for result in (x for x in sickrage.app.main_db.get_many('tv_episodes', show.indexerid) if
                       x['season'] > 0 and datetime.date.today().toordinal() > x['airdate'] >= from_date.toordinal()):

            curStatus, curQuality = Quality.splitCompositeStatus(int(result["status"] or -1))

            # if we need a better one then say yes
            if curStatus not in {WANTED, DOWNLOADED, SNATCHED, SNATCHED_PROPER}:
                continue

            if curStatus != WANTED:
                if bestQualities:
                    if curQuality in bestQualities:
                        continue
                    elif curQuality != Quality.UNKNOWN and curQuality > max(bestQualities):
                        continue
                else:
                    if curQuality in anyQualities:
                        continue
                    elif curQuality != Quality.UNKNOWN and curQuality > max(anyQualities):
                        continue

            # skip upgrading quality of downloaded episodes if enabled
            if curStatus == DOWNLOADED and show.skip_downloaded:
                continue

            epObj = show.get_episode(int(result["season"]), int(result["episode"]))
            wanted.append(epObj)

        return wanted
Beispiel #19
0
    def _getProperList(self):
        """
        Walk providers for propers
        """
        propers = {}

        search_date = datetime.datetime.today() - datetime.timedelta(days=2)

        origThreadName = threading.currentThread().getName()

        # for each provider get a list of the
        for providerID, providerObj in sickrage.srCore.providersDict.sort(
                randomize=sickrage.srCore.srConfig.RANDOMIZE_PROVIDERS).items():
            # check provider type and provider is enabled
            if not sickrage.srCore.srConfig.USE_NZBS and providerObj.type in [NZBProvider.type, NewznabProvider.type]:
                continue
            elif not sickrage.srCore.srConfig.USE_TORRENTS and providerObj.type in [TorrentProvider.type,
                                                                                    TorrentRssProvider.type]:
                continue
            elif not providerObj.isEnabled:
                continue

            threading.currentThread().setName(origThreadName + " :: [" + providerObj.name + "]")

            sickrage.srCore.srLogger.info("Searching for any new PROPER releases from " + providerObj.name)

            try:
                curPropers = providerObj.findPropers(search_date)
            except AuthException as e:
                sickrage.srCore.srLogger.debug("Authentication error: {}".format(e.message))
                continue
            except Exception as e:
                sickrage.srCore.srLogger.debug(
                    "Error while searching " + providerObj.name + ", skipping: {}".format(e.message))
                sickrage.srCore.srLogger.debug(traceback.format_exc())
                continue

            # if they haven't been added by a different provider than add the proper to the list
            for x in curPropers:
                if not re.search(r'(^|[\. _-])(proper|repack)([\. _-]|$)', x.name, re.I):
                    sickrage.srCore.srLogger.debug('findPropers returned a non-proper, we have caught and skipped it.')
                    continue

                name = self._genericName(x.name)
                if not name in propers:
                    sickrage.srCore.srLogger.debug("Found new proper: " + x.name)
                    x.provider = providerObj
                    propers[name] = x

            threading.currentThread().setName(origThreadName)

        # take the list of unique propers and get it sorted by
        sortedPropers = sorted(propers.values(), key=operator.attrgetter('date'), reverse=True)
        finalPropers = []

        for curProper in sortedPropers:

            try:
                myParser = NameParser(False)
                parse_result = myParser.parse(curProper.name)
            except InvalidNameException:
                sickrage.srCore.srLogger.debug(
                    "Unable to parse the filename " + curProper.name + " into a valid episode")
                continue
            except InvalidShowException:
                sickrage.srCore.srLogger.debug("Unable to parse the filename " + curProper.name + " into a valid show")
                continue

            if not parse_result.series_name:
                continue

            if not parse_result.episode_numbers:
                sickrage.srCore.srLogger.debug(
                    "Ignoring " + curProper.name + " because it's for a full season rather than specific episode")
                continue

            sickrage.srCore.srLogger.debug(
                "Successful match! Result " + parse_result.original_name + " matched to show " + parse_result.show.name)

            # set the indexerid in the db to the show's indexerid
            curProper.indexerid = parse_result.show.indexerid

            # set the indexer in the db to the show's indexer
            curProper.indexer = parse_result.show.indexer

            # populate our Proper instance
            curProper.show = parse_result.show
            curProper.season = parse_result.season_number if parse_result.season_number is not None else 1
            curProper.episode = parse_result.episode_numbers[0]
            curProper.release_group = parse_result.release_group
            curProper.version = parse_result.version
            curProper.quality = Quality.nameQuality(curProper.name, parse_result.is_anime)
            curProper.content = None

            # filter release
            bestResult = pickBestResult(curProper, parse_result.show)
            if not bestResult:
                sickrage.srCore.srLogger.debug("Proper " + curProper.name + " were rejected by our release filters.")
                continue

            # only get anime proper if it has release group and version
            if bestResult.show.is_anime:
                if not bestResult.release_group and bestResult.version == -1:
                    sickrage.srCore.srLogger.debug(
                        "Proper " + bestResult.name + " doesn't have a release group and version, ignoring it")
                    continue

            # check if we actually want this proper (if it's the right quality)            
            sqlResults = main_db.MainDB().select(
                "SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?",
                [bestResult.indexerid, bestResult.season, bestResult.episode])
            if not sqlResults:
                continue

            # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones)
            oldStatus, oldQuality = Quality.splitCompositeStatus(int(sqlResults[0]["status"]))
            if oldStatus not in (DOWNLOADED, SNATCHED) or oldQuality != bestResult.quality:
                continue

            # check if we actually want this proper (if it's the right release group and a higher version)
            if bestResult.show.is_anime:
                sqlResults = main_db.MainDB().select(
                    "SELECT release_group, version FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?",
                    [bestResult.indexerid, bestResult.season, bestResult.episode])

                oldVersion = int(sqlResults[0]["version"])
                oldRelease_group = (sqlResults[0]["release_group"])

                if oldVersion > -1 and oldVersion < bestResult.version:
                    sickrage.srCore.srLogger.info(
                        "Found new anime v" + str(bestResult.version) + " to replace existing v" + str(oldVersion))
                else:
                    continue

                if oldRelease_group != bestResult.release_group:
                    sickrage.srCore.srLogger.info(
                        "Skipping proper from release group: " + bestResult.release_group + ", does not match existing release group: " + oldRelease_group)
                    continue

            # if the show is in our list and there hasn't been a proper already added for that particular episode then add it to our list of propers
            if bestResult.indexerid != -1 and (bestResult.indexerid, bestResult.season, bestResult.episode) not in map(
                    operator.attrgetter('indexerid', 'season', 'episode'), finalPropers):
                sickrage.srCore.srLogger.info("Found a proper that we need: " + str(bestResult.name))
                finalPropers.append(bestResult)

        return finalPropers
Beispiel #20
0
def _replace_map(episode):
    """
    Generates a replacement map for this episode which maps all possible custom naming patterns to the correct
    value for this episode.

    Returns: A dict with patterns as the keys and their replacement values as the values.
    """

    ep_name = _ep_name(episode)

    def dot(name):
        return sanitizeSceneName(name)

    def us(name):
        return re.sub('[ -]', '_', name)

    def release_name(name):
        if name:
            name = remove_non_release_groups(remove_extension(name))
        return name

    def release_group(show, name):
        if name:
            name = remove_non_release_groups(remove_extension(name))
        else:
            return ""

        try:
            np = NameParser(name, showObj=show, naming_pattern=True)
            parse_result = np.parse(name)
        except (InvalidNameException, InvalidShowException) as e:
            sickrage.LOGGER.debug(
                "Unable to get parse release_group: {}".format(e))
            return ''

        if not parse_result.release_group:
            return ''
        return parse_result.release_group

    _, epQual = Quality.splitCompositeStatus(episode.status)  # @UnusedVariable

    if sickrage.NAMING_STRIP_YEAR:
        show_name = re.sub(r"\(\d+\)$", "", episode.show.name).rstrip()
    else:
        show_name = episode.show.name

    # try to get the release group
    rel_grp = {}
    rel_grp[b"SiCKRAGE"] = 'SiCKRAGE'
    if hasattr(episode, 'location'):  # from the location name
        rel_grp[b'location'] = release_group(episode.show, episode.location)
        if not rel_grp[b'location']:
            del rel_grp[b'location']
    if hasattr(episode,
               '_release_group'):  # from the release group field in db
        rel_grp[b'database'] = episode._release_group
        if not rel_grp[b'database']:
            del rel_grp[b'database']
    if hasattr(episode, 'release_name'):  # from the release name field in db
        rel_grp[b'release_name'] = release_group(episode.show,
                                                 episode.release_name)
        if not rel_grp[b'release_name']:
            del rel_grp[b'release_name']

    # use release_group, release_name, location in that order
    if 'database' in rel_grp:
        relgrp = 'database'
    elif 'release_name' in rel_grp:
        relgrp = 'release_name'
    elif 'location' in rel_grp:
        relgrp = 'location'
    else:
        relgrp = 'SiCKRAGE'

    # try to get the release encoder to comply with scene naming standards
    encoder = Quality.sceneQualityFromName(
        episode.release_name.replace(rel_grp[relgrp], ""), epQual)
    if encoder:
        sickrage.LOGGER.debug("Found codec for '" + show_name + ": " +
                              ep_name + "'.")

    return {
        '%SN': show_name,
        '%S.N': dot(show_name),
        '%S_N': us(show_name),
        '%EN': ep_name,
        '%E.N': dot(ep_name),
        '%E_N': us(ep_name),
        '%QN': Quality.qualityStrings[epQual],
        '%Q.N': dot(Quality.qualityStrings[epQual]),
        '%Q_N': us(Quality.qualityStrings[epQual]),
        '%SQN': Quality.sceneQualityStrings[epQual] + encoder,
        '%SQ.N': dot(Quality.sceneQualityStrings[epQual] + encoder),
        '%SQ_N': us(Quality.sceneQualityStrings[epQual] + encoder),
        '%S': str(episode.season),
        '%0S': '%02d' % episode.season,
        '%E': str(episode.episode),
        '%0E': '%02d' % episode.episode,
        '%XS': str(episode.scene_season),
        '%0XS': '%02d' % episode.scene_season,
        '%XE': str(episode.scene_episode),
        '%0XE': '%02d' % episode.scene_episode,
        '%AB': '%(#)03d' % {
            '#': episode.absolute_number
        },
        '%XAB': '%(#)03d' % {
            '#': episode.scene_absolute_number
        },
        '%RN': release_name(episode.release_name),
        '%RG': rel_grp[relgrp],
        '%CRG': rel_grp[relgrp].upper(),
        '%AD': str(episode.airdate).replace('-', ' '),
        '%A.D': str(episode.airdate).replace('-', '.'),
        '%A_D': us(str(episode.airdate)),
        '%A-D': str(episode.airdate),
        '%Y': str(episode.airdate.year),
        '%M': str(episode.airdate.month),
        '%D': str(episode.airdate.day),
        '%0M': '%02d' % episode.airdate.month,
        '%0D': '%02d' % episode.airdate.day,
        '%RT': "PROPER" if episode.is_proper else "",
    }
Beispiel #21
0
def makeSceneSeasonSearchString(show, ep_obj, extraSearchType=None):
    numseasons = 0

    if show.air_by_date or show.sports:
        # the search string for air by date shows is just
        seasonStrings = [str(ep_obj.airdate).split('-')[0]]
    elif show.is_anime:
        seasonEps = show.getAllEpisodes(ep_obj.season)

        # get show qualities
        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        # compile a list of all the episode numbers we need in this 'season'
        seasonStrings = []
        for episode in seasonEps:

            # get quality of the episode
            curCompositeStatus = episode.status
            curStatus, curQuality = Quality.splitCompositeStatus(
                curCompositeStatus)

            if bestQualities:
                highestBestQuality = max(bestQualities)
            else:
                highestBestQuality = 0

            # if we need a better one then add it to the list of episodes to fetch
            if (curStatus in (DOWNLOADED, SNATCHED) and
                    curQuality < highestBestQuality) or curStatus == WANTED:
                ab_number = episode.scene_absolute_number
                if ab_number > 0:
                    seasonStrings.append("%02d" % ab_number)

    else:
        numseasonsSQlResult = main_db.MainDB().select(
            "SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0",
            [show.indexerid])

        if numseasonsSQlResult:
            numseasons = int(numseasonsSQlResult[0][0])
        seasonStrings = ["S%02d" % int(ep_obj.scene_season)]

    showNames = set(makeSceneShowSearchStrings(show, ep_obj.scene_season))

    toReturn = []

    # search each show name
    for curShow in showNames:
        # most providers all work the same way
        if not extraSearchType:
            # if there's only one season then we can just use the show name straight up
            if numseasons == 1:
                toReturn.append(curShow)
            # for providers that don't allow multiple searches in one request we only search for Sxx style stuff
            else:
                for cur_season in seasonStrings:
                    if ep_obj.show.is_anime:
                        if ep_obj.show.release_groups is not None:
                            if len(show.release_groups.whitelist) > 0:
                                for keyword in show.release_groups.whitelist:
                                    toReturn.append(keyword + '.' + curShow +
                                                    "." + cur_season)
                    else:
                        toReturn.append(curShow + "." + cur_season)

    return toReturn
Beispiel #22
0
def _replace_map(episode):
    """
    Generates a replacement map for this episode which maps all possible custom naming patterns to the correct
    value for this episode.

    Returns: A dict with patterns as the keys and their replacement values as the values.
    """

    ep_name = _ep_name(episode)

    def dot(name):
        return sanitizeSceneName(name)

    def us(name):
        return re.sub('[ -]', '_', name)

    def release_name(name):
        if name:
            name = remove_non_release_groups(remove_extension(name))
        return name

    def release_group(show, name):
        if name:
            name = remove_non_release_groups(remove_extension(name))
        else:
            return ""

        try:
            np = NameParser(name, showObj=show, naming_pattern=True)
            parse_result = np.parse(name)
        except (InvalidNameException, InvalidShowException) as e:
            sickrage.LOGGER.debug("Unable to get parse release_group: {}".format(e))
            return ''

        if not parse_result.release_group:
            return ''
        return parse_result.release_group

    _, epQual = Quality.splitCompositeStatus(episode.status)  # @UnusedVariable

    if sickrage.NAMING_STRIP_YEAR:
        show_name = re.sub(r"\(\d+\)$", "", episode.show.name).rstrip()
    else:
        show_name = episode.show.name

    # try to get the release group
    rel_grp = {}
    rel_grp[b"SiCKRAGE"] = 'SiCKRAGE'
    if hasattr(episode, 'location'):  # from the location name
        rel_grp[b'location'] = release_group(episode.show, episode.location)
        if not rel_grp[b'location']:
            del rel_grp[b'location']
    if hasattr(episode, '_release_group'):  # from the release group field in db
        rel_grp[b'database'] = episode._release_group
        if not rel_grp[b'database']:
            del rel_grp[b'database']
    if hasattr(episode, 'release_name'):  # from the release name field in db
        rel_grp[b'release_name'] = release_group(episode.show, episode.release_name)
        if not rel_grp[b'release_name']:
            del rel_grp[b'release_name']

    # use release_group, release_name, location in that order
    if 'database' in rel_grp:
        relgrp = 'database'
    elif 'release_name' in rel_grp:
        relgrp = 'release_name'
    elif 'location' in rel_grp:
        relgrp = 'location'
    else:
        relgrp = 'SiCKRAGE'

    # try to get the release encoder to comply with scene naming standards
    encoder = Quality.sceneQualityFromName(episode.release_name.replace(rel_grp[relgrp], ""), epQual)
    if encoder:
        sickrage.LOGGER.debug("Found codec for '" + show_name + ": " + ep_name + "'.")

    return {
        '%SN': show_name,
        '%S.N': dot(show_name),
        '%S_N': us(show_name),
        '%EN': ep_name,
        '%E.N': dot(ep_name),
        '%E_N': us(ep_name),
        '%QN': Quality.qualityStrings[epQual],
        '%Q.N': dot(Quality.qualityStrings[epQual]),
        '%Q_N': us(Quality.qualityStrings[epQual]),
        '%SQN': Quality.sceneQualityStrings[epQual] + encoder,
        '%SQ.N': dot(Quality.sceneQualityStrings[epQual] + encoder),
        '%SQ_N': us(Quality.sceneQualityStrings[epQual] + encoder),
        '%S': str(episode.season),
        '%0S': '%02d' % episode.season,
        '%E': str(episode.episode),
        '%0E': '%02d' % episode.episode,
        '%XS': str(episode.scene_season),
        '%0XS': '%02d' % episode.scene_season,
        '%XE': str(episode.scene_episode),
        '%0XE': '%02d' % episode.scene_episode,
        '%AB': '%(#)03d' % {'#': episode.absolute_number},
        '%XAB': '%(#)03d' % {'#': episode.scene_absolute_number},
        '%RN': release_name(episode.release_name),
        '%RG': rel_grp[relgrp],
        '%CRG': rel_grp[relgrp].upper(),
        '%AD': str(episode.airdate).replace('-', ' '),
        '%A.D': str(episode.airdate).replace('-', '.'),
        '%A_D': us(str(episode.airdate)),
        '%A-D': str(episode.airdate),
        '%Y': str(episode.airdate.year),
        '%M': str(episode.airdate.month),
        '%D': str(episode.airdate.day),
        '%0M': '%02d' % episode.airdate.month,
        '%0D': '%02d' % episode.airdate.day,
        '%RT': "PROPER" if episode.is_proper else "",
    }
    def _getProperList(self):
        """
        Walk providers for propers
        """
        propers = {}

        search_date = datetime.datetime.today() - datetime.timedelta(days=2)

        origThreadName = threading.currentThread().getName()

        # for each provider get a list of the
        for providerID, providerObj in sickrage.srCore.providersDict.sort(
                randomize=sickrage.srCore.srConfig.RANDOMIZE_PROVIDERS).items(
                ):
            # check provider type and provider is enabled
            if not sickrage.srCore.srConfig.USE_NZBS and providerObj.type in [
                    NZBProvider.type, NewznabProvider.type
            ]:
                continue
            elif not sickrage.srCore.srConfig.USE_TORRENTS and providerObj.type in [
                    TorrentProvider.type, TorrentRssProvider.type
            ]:
                continue
            elif not providerObj.isEnabled:
                continue

            threading.currentThread().setName(origThreadName + " :: [" +
                                              providerObj.name + "]")

            sickrage.srCore.srLogger.info(
                "Searching for any new PROPER releases from " +
                providerObj.name)

            try:
                curPropers = providerObj.find_propers(search_date)
            except AuthException as e:
                sickrage.srCore.srLogger.warning(
                    "Authentication error: {}".format(e.message))
                continue
            except Exception as e:
                sickrage.srCore.srLogger.debug(
                    "Error while searching " + providerObj.name +
                    ", skipping: {}".format(e.message))
                sickrage.srCore.srLogger.debug(traceback.format_exc())
                continue

            # if they haven't been added by a different provider than add the proper to the list
            for x in curPropers:
                if not re.search(r'(^|[\. _-])(proper|repack)([\. _-]|$)',
                                 x.name, re.I):
                    sickrage.srCore.srLogger.debug(
                        'findPropers returned a non-proper, we have caught and skipped it.'
                    )
                    continue

                name = self._genericName(x.name)
                if not name in propers:
                    sickrage.srCore.srLogger.debug("Found new proper: " +
                                                   x.name)
                    x.provider = providerObj
                    propers[name] = x

            threading.currentThread().setName(origThreadName)

        # take the list of unique propers and get it sorted by
        sortedPropers = sorted(propers.values(),
                               key=operator.attrgetter('date'),
                               reverse=True)
        finalPropers = []

        for curProper in sortedPropers:

            try:
                myParser = NameParser(False)
                parse_result = myParser.parse(curProper.name)
            except InvalidNameException:
                sickrage.srCore.srLogger.debug(
                    "Unable to parse the filename " + curProper.name +
                    " into a valid episode")
                continue
            except InvalidShowException:
                sickrage.srCore.srLogger.debug(
                    "Unable to parse the filename " + curProper.name +
                    " into a valid show")
                continue

            if not parse_result.series_name:
                continue

            if not parse_result.episode_numbers:
                sickrage.srCore.srLogger.debug(
                    "Ignoring " + curProper.name +
                    " because it's for a full season rather than specific episode"
                )
                continue

            sickrage.srCore.srLogger.debug("Successful match! Result " +
                                           parse_result.original_name +
                                           " matched to show " +
                                           parse_result.show.name)

            # set the indexerid in the db to the show's indexerid
            curProper.indexerid = parse_result.show.indexerid

            # set the indexer in the db to the show's indexer
            curProper.indexer = parse_result.show.indexer

            # populate our Proper instance
            curProper.show = parse_result.show
            curProper.season = parse_result.season_number if parse_result.season_number is not None else 1
            curProper.episode = parse_result.episode_numbers[0]
            curProper.release_group = parse_result.release_group
            curProper.version = parse_result.version
            curProper.quality = Quality.nameQuality(curProper.name,
                                                    parse_result.is_anime)
            curProper.content = None

            # filter release
            bestResult = pickBestResult(curProper, parse_result.show)
            if not bestResult:
                sickrage.srCore.srLogger.debug(
                    "Proper " + curProper.name +
                    " were rejected by our release filters.")
                continue

            # only get anime proper if it has release group and version
            if bestResult.show.is_anime:
                if not bestResult.release_group and bestResult.version == -1:
                    sickrage.srCore.srLogger.debug(
                        "Proper " + bestResult.name +
                        " doesn't have a release group and version, ignoring it"
                    )
                    continue

            # check if we actually want this proper (if it's the right quality)
            dbData = [
                x['doc'] for x in sickrage.srCore.mainDB().db.get_many(
                    'tv_episodes', bestResult.indexerid, with_doc=True)
                if x['doc']['season'] == bestResult.season
                and x['doc']['episode'] == bestResult.episode
            ]
            if not dbData: continue

            # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones)
            oldStatus, oldQuality = Quality.splitCompositeStatus(
                int(dbData[0]["status"]))
            if oldStatus not in (DOWNLOADED,
                                 SNATCHED) or oldQuality != bestResult.quality:
                continue

            # check if we actually want this proper (if it's the right release group and a higher version)
            if bestResult.show.is_anime:
                dbData = [
                    x['doc'] for x in sickrage.srCore.mainDB.db.get_many(
                        'tv_episodes', bestResult.indexerid, with_doc=True)
                    if x['doc']['season'] == bestResult.season
                    and x['doc']['episode'] == bestResult.episode
                ]

                oldVersion = int(dbData[0]["version"])
                oldRelease_group = (dbData[0]["release_group"])

                if -1 < oldVersion < bestResult.version:
                    sickrage.srCore.srLogger.info("Found new anime v" +
                                                  str(bestResult.version) +
                                                  " to replace existing v" +
                                                  str(oldVersion))
                else:
                    continue

                if oldRelease_group != bestResult.release_group:
                    sickrage.srCore.srLogger.info(
                        "Skipping proper from release group: " +
                        bestResult.release_group +
                        ", does not match existing release group: " +
                        oldRelease_group)
                    continue

            # if the show is in our list and there hasn't been a proper already added for that particular episode then add it to our list of propers
            if bestResult.indexerid != -1 and (
                    bestResult.indexerid, bestResult.season,
                    bestResult.episode) not in map(
                        operator.attrgetter('indexerid', 'season', 'episode'),
                        finalPropers):
                sickrage.srCore.srLogger.info("Found a proper that we need: " +
                                              str(bestResult.name))
                finalPropers.append(bestResult)

        return finalPropers
Beispiel #24
0
def makeSceneSeasonSearchString(show, ep_obj, extraSearchType=None):
    numseasons = 0

    if show.air_by_date or show.sports:
        # the search string for air by date shows is just
        seasonStrings = [str(ep_obj.airdate).split('-')[0]]
    elif show.is_anime:
        seasonEps = show.get_all_episodes(ep_obj.season)

        # get show qualities
        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        # compile a list of all the episode numbers we need in this 'season'
        seasonStrings = []
        for episode in seasonEps:

            # get quality of the episode
            curCompositeStatus = episode.status
            curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus)

            if bestQualities:
                highestBestQuality = max(bestQualities)
            else:
                highestBestQuality = 0

            # if we need a better one then add it to the list of episodes to fetch
            if (curStatus in (
                    DOWNLOADED,
                    SNATCHED) and curQuality < highestBestQuality) or curStatus == WANTED:
                ab_number = episode.scene_absolute_number
                if ab_number > 0:
                    seasonStrings.append("%02d" % ab_number)

    else:
        numseasons = len({x['season'] for x in sickrage.app.main_db.get_many('tv_episodes', show.indexerid)
                          if x['season'] != 0})

        seasonStrings = ["S%02d" % int(ep_obj.scene_season)]

    showNames = set(makeSceneShowSearchStrings(show, ep_obj.scene_season))

    toReturn = []

    # search each show name
    for curShow in showNames:
        # most providers all work the same way
        if not extraSearchType:
            # if there's only one season then we can just use the show name straight up
            if numseasons == 1:
                toReturn.append(curShow)
            # for providers that don't allow multiple searches in one request we only search for Sxx style stuff
            else:
                for cur_season in seasonStrings:
                    if ep_obj.show.is_anime:
                        if ep_obj.show.release_groups is not None:
                            if len(show.release_groups.whitelist) > 0:
                                for keyword in show.release_groups.whitelist:
                                    toReturn.append(keyword + '.' + curShow + "." + cur_season)
                    else:
                        toReturn.append(curShow + "." + cur_season)

    return toReturn
Beispiel #25
0
    def _getProperList(self):
        """
        Walk providers for propers
        """
        propers = {}

        search_date = datetime.datetime.today() - datetime.timedelta(days=2)

        origThreadName = threading.currentThread().getName()

        recently_aired = []
        for show in sickrage.app.showlist:
            self._lastProperSearch = self._get_lastProperSearch(show.indexerid)

            for episode in sickrage.app.main_db.get_many('tv_episodes', show.indexerid):
                if episode['airdate'] >= str(search_date.toordinal()):
                    if episode['status'] in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_BEST:
                        recently_aired += [episode]

            self._set_lastProperSearch(show.indexerid, datetime.datetime.today().toordinal())

        if not recently_aired:
            sickrage.app.log.info('No recently aired episodes, nothing to search for')
            return []

        # for each provider get a list of the
        for providerID, providerObj in sickrage.app.search_providers.sort(
                randomize=sickrage.app.config.randomize_providers).items():
            # check provider type and provider is enabled
            if not sickrage.app.config.use_nzbs and providerObj.type in [NZBProvider.type,
                                                                         NewznabProvider.type]:
                continue
            elif not sickrage.app.config.use_torrents and providerObj.type in [TorrentProvider.type,
                                                                               TorrentRssProvider.type]:
                continue
            elif not providerObj.isEnabled:
                continue

            threading.currentThread().setName(origThreadName + " :: [" + providerObj.name + "]")

            sickrage.app.log.info("Searching for any new PROPER releases from " + providerObj.name)

            try:
                curPropers = providerObj.find_propers(recently_aired)
            except AuthException as e:
                sickrage.app.log.warning("Authentication error: {}".format(e))
                continue
            except Exception as e:
                sickrage.app.log.debug(
                    "Error while searching " + providerObj.name + ", skipping: {}".format(e))
                sickrage.app.log.debug(traceback.format_exc())
                continue

            # if they haven't been added by a different provider than add the proper to the list
            for x in curPropers:
                if not re.search(r'(^|[. _-])(proper|repack)([. _-]|$)', x.name, re.I):
                    sickrage.app.log.debug('findPropers returned a non-proper, we have caught and skipped it.')
                    continue

                name = self._genericName(x.name)
                if name not in propers:
                    sickrage.app.log.debug("Found new proper: " + x.name)
                    x.provider = providerObj
                    propers[name] = x

            threading.currentThread().setName(origThreadName)

        # take the list of unique propers and get it sorted by
        sortedPropers = sorted(propers.values(), key=operator.attrgetter('date'), reverse=True)
        finalPropers = []

        for curProper in sortedPropers:
            try:
                myParser = NameParser(False)
                parse_result = myParser.parse(curProper.name)
            except InvalidNameException:
                sickrage.app.log.debug(
                    "Unable to parse the filename " + curProper.name + " into a valid episode")
                continue
            except InvalidShowException:
                sickrage.app.log.debug("Unable to parse the filename " + curProper.name + " into a valid show")
                continue

            if not parse_result.series_name:
                continue

            if not parse_result.episode_numbers:
                sickrage.app.log.debug(
                    "Ignoring " + curProper.name + " because it's for a full season rather than specific episode")
                continue

            sickrage.app.log.debug(
                "Successful match! Result " + parse_result.original_name + " matched to show " + parse_result.show.name)

            # set the indexerid in the db to the show's indexerid
            curProper.indexerid = parse_result.indexerid

            # set the indexer in the db to the show's indexer
            curProper.indexer = parse_result.show.indexer

            # populate our Proper instance
            curProper.show = parse_result.show
            curProper.season = parse_result.season_number if parse_result.season_number is not None else 1
            curProper.episode = parse_result.episode_numbers[0]
            curProper.release_group = parse_result.release_group
            curProper.version = parse_result.version
            curProper.quality = Quality.nameQuality(curProper.name, parse_result.is_anime)
            curProper.content = None

            # filter release
            bestResult = pickBestResult(curProper, parse_result.show)
            if not bestResult:
                sickrage.app.log.debug("Proper " + curProper.name + " were rejected by our release filters.")
                continue

            # only get anime proper if it has release group and version
            if bestResult.show.is_anime:
                if not bestResult.release_group and bestResult.version == -1:
                    sickrage.app.log.debug(
                        "Proper " + bestResult.name + " doesn't have a release group and version, ignoring it")
                    continue

            # check if we actually want this proper (if it's the right quality)            
            dbData = [x for x in sickrage.app.main_db().get_many('tv_episodes', bestResult.indexerid)
                      if x['season'] == bestResult.season and x['episode'] == bestResult.episode]

            if not dbData:
                continue

            # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones)
            oldStatus, oldQuality = Quality.splitCompositeStatus(int(dbData[0]["status"]))
            if oldStatus not in (DOWNLOADED, SNATCHED) or oldQuality != bestResult.quality:
                continue

            # check if we actually want this proper (if it's the right release group and a higher version)
            if bestResult.show.is_anime:
                dbData = [x for x in sickrage.app.main_db.get_many('tv_episodes', bestResult.indexerid)
                          if x['season'] == bestResult.season and x['episode'] == bestResult.episode]

                oldVersion = int(dbData[0]["version"])
                oldRelease_group = (dbData[0]["release_group"])

                if -1 < oldVersion < bestResult.version:
                    sickrage.app.log.info(
                        "Found new anime v" + str(bestResult.version) + " to replace existing v" + str(oldVersion))
                else:
                    continue

                if oldRelease_group != bestResult.release_group:
                    sickrage.app.log.info(
                        "Skipping proper from release group: " + bestResult.release_group + ", does not match existing release group: " + oldRelease_group)
                    continue

            # if the show is in our list and there hasn't been a proper already added for that particular episode then add it to our list of propers
            if bestResult.indexerid != -1 and (bestResult.indexerid, bestResult.season, bestResult.episode) not in map(
                    operator.attrgetter('indexerid', 'season', 'episode'), finalPropers):
                sickrage.app.log.info("Found a proper that we need: " + str(bestResult.name))
                finalPropers.append(bestResult)

        return finalPropers