Example #1
0
            curProper.version = parse_result.version
            curProper.quality = Quality.nameQuality(curProper.name, parse_result.is_anime)

            # only get anime proper if it has release group and version
            if parse_result.is_anime:
                if not curProper.release_group and curProper.version == -1:
                    logger.log(u"Proper " + curProper.name + " doesn't have a release group and version, ignoring it",
                               logger.DEBUG)
                    continue

            if not show_name_helpers.filterBadReleases(curProper.name, parse=False):
                logger.log(u"Proper " + curProper.name + " isn't a valid scene release that we want, ignoring it",
                           logger.DEBUG)
                continue

            if parse_result.show.rls_ignore_words and search.filter_release_name(curProper.name,
                                                                                 parse_result.show.rls_ignore_words):
                logger.log(
                    u"Ignoring " + curProper.name + " based on ignored words filter: " + parse_result.show.rls_ignore_words,
                    logger.INFO)
                continue

            if parse_result.show.rls_require_words and not search.filter_release_name(curProper.name,
                                                                                      parse_result.show.rls_require_words):
                logger.log(
                    u"Ignoring " + curProper.name + " based on required words filter: " + parse_result.show.rls_require_words,
                    logger.INFO)
                continue

            # check if we actually want this proper (if it's the right quality)
            myDB = db.DBConnection()
            sqlResults = myDB.select("SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?",
Example #2
0
            if parse_result.is_anime:
                if not curProper.release_group and curProper.version == -1:
                    logger.log(
                        u"Proper " + curProper.name +
                        " doesn't have a release group and version, ignoring it",
                        logger.DEBUG)
                    continue

            if not show_name_helpers.filterBadReleases(curProper.name):
                logger.log(
                    u"Proper " + curProper.name +
                    " isn't a valid scene release that we want, ignoring it",
                    logger.DEBUG)
                continue

            if parse_result.show.rls_ignore_words and search.filter_release_name(
                    curProper.name, parse_result.show.rls_ignore_words):
                logger.log(
                    u"Ignoring " + curProper.name +
                    " based on ignored words filter: " +
                    parse_result.show.rls_ignore_words, logger.MESSAGE)
                continue

            if parse_result.show.rls_require_words and not search.filter_release_name(
                    curProper.name, parse_result.show.rls_require_words):
                logger.log(
                    u"Ignoring " + curProper.name +
                    " based on required words filter: " +
                    parse_result.show.rls_require_words, logger.MESSAGE)
                continue

            # check if we actually want this proper (if it's the right quality)
Example #3
0
class ProperFinder():
    def __init__(self):
        self.updateInterval = datetime.timedelta(hours=1)

    def run(self):

        if not sickbeard.DOWNLOAD_PROPERS:
            return

        # look for propers every night at 1 AM
        updateTime = datetime.time(hour=1)

        logger.log(u"Checking proper time", logger.DEBUG)

        hourDiff = datetime.datetime.today().time().hour - updateTime.hour

        # if it's less than an interval after the update time then do an update
        if hourDiff >= 0 and hourDiff < self.updateInterval.seconds / 3600:
            logger.log(u"Beginning the search for new propers")
        else:
            return

        propers = self._getProperList()

        self._downloadPropers(propers)

    def _getProperList(self):

        propers = {}

        # for each provider get a list of the propers
        for curProvider in providers.sortedProviderList():

            if not curProvider.isActive():
                continue

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

            logger.log(u"Searching for any new PROPER releases from " +
                       curProvider.name)
            try:
                curPropers = curProvider.findPropers(search_date)
            except exceptions.AuthException, e:
                logger.log(u"Authentication error: " + ex(e), logger.ERROR)
                continue

            # if they haven't been added by a different provider than add the proper to the list
            for x in curPropers:
                name = self._genericName(x.name)

                if not name in propers:
                    logger.log(u"Found new proper: " + x.name, logger.DEBUG)
                    x.provider = curProvider
                    propers[name] = x

        # 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:

            # parse the file name
            try:
                myParser = NameParser(False)
                parse_result = myParser.parse(curProper.name)
            except InvalidNameException:
                logger.log(
                    u"Unable to parse the filename " + curProper.name +
                    " into a valid episode", logger.DEBUG)
                continue

            if not parse_result.episode_numbers:
                logger.log(
                    u"Ignoring " + curProper.name +
                    " because it's for a full season rather than specific episode",
                    logger.DEBUG)
                continue

            # populate our Proper instance
            if parse_result.air_by_date:
                curProper.season = -1
                curProper.episode = parse_result.air_date
            else:
                curProper.season = parse_result.season_number if parse_result.season_number != None else 1
                curProper.episode = parse_result.episode_numbers[0]
            curProper.quality = Quality.nameQuality(curProper.name)

            # for each show in our list
            for curShow in sickbeard.showList:

                if not parse_result.series_name:
                    continue

                genericName = self._genericName(parse_result.series_name)

                # get the scene name masks
                sceneNames = set(
                    show_name_helpers.makeSceneShowSearchStrings(curShow))

                # for each scene name mask
                for curSceneName in sceneNames:

                    # if it matches
                    if genericName == self._genericName(curSceneName):
                        logger.log(
                            u"Successful match! Result " +
                            parse_result.series_name + " matched to show " +
                            curShow.name, logger.DEBUG)

                        # set the tvdbid in the db to the show's tvdbid
                        curProper.tvdbid = curShow.tvdbid

                        # since we found it, break out
                        break

                # if we found something in the inner for loop break out of this one
                if curProper.tvdbid != -1:
                    break

            if curProper.tvdbid == -1:
                continue

            if not show_name_helpers.filterBadReleases(curProper.name):
                logger.log(
                    u"Proper " + curProper.name +
                    " isn't a valid scene release that we want, ignoring it",
                    logger.DEBUG)
                continue

            show = helpers.findCertainShow(sickbeard.showList,
                                           curProper.tvdbid)
            if not show:
                logger.log(
                    u"Unable to find the show with tvdbid " +
                    str(curProper.tvdbid), logger.ERROR)
                continue

            if show.rls_ignore_words and search.filter_release_name(
                    curProper.name, show.rls_ignore_words):
                logger.log(
                    u"Ignoring " + curProper.name +
                    " based on ignored words filter: " + show.rls_ignore_words,
                    logger.MESSAGE)
                continue

            if show.rls_require_words and not search.filter_release_name(
                    curProper.name, show.rls_require_words):
                logger.log(
                    u"Ignoring " + curProper.name +
                    " based on required words filter: " +
                    show.rls_require_words, logger.MESSAGE)
                continue

            # if we have an air-by-date show then get the real season/episode numbers
            if curProper.season == -1 and curProper.tvdbid:

                tvdb_lang = show.lang
                # There's gotta be a better way of doing this but we don't wanna
                # change the language value elsewhere
                ltvdb_api_parms = sickbeard.TVDB_API_PARMS.copy()

                if tvdb_lang and not tvdb_lang == 'en':
                    ltvdb_api_parms['language'] = tvdb_lang

                try:
                    t = tvdb_api.Tvdb(**ltvdb_api_parms)
                    epObj = t[curProper.tvdbid].airedOn(curProper.episode)[0]
                    curProper.season = int(epObj["seasonnumber"])
                    curProper.episodes = [int(epObj["episodenumber"])]
                except tvdb_exceptions.tvdb_episodenotfound:
                    logger.log(
                        u"Unable to find episode with date " +
                        str(curProper.episode) + " for show " +
                        parse_result.series_name + ", skipping",
                        logger.WARNING)
                    continue

            # check if we actually want this proper (if it's the right quality)
            sqlResults = db.DBConnection().select(
                "SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?",
                [curProper.tvdbid, curProper.season, curProper.episode])
            if not sqlResults:
                continue
            oldStatus, oldQuality = Quality.splitCompositeStatus(
                int(sqlResults[0]["status"]))

            # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones)
            if oldStatus not in (DOWNLOADED,
                                 SNATCHED) or oldQuality != curProper.quality:
                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 curProper.tvdbid != -1 and (curProper.tvdbid, curProper.season,
                                           curProper.episode) not in map(
                                               operator.attrgetter(
                                                   'tvdbid', 'season',
                                                   'episode'), finalPropers):
                logger.log(u"Found a proper that we need: " +
                           str(curProper.name))
                finalPropers.append(curProper)

        return finalPropers
Example #4
0
class ProperFinder():
    def __init__(self):
        self.amActive = False
        self.updateInterval = datetime.timedelta(hours=1)

        check_propers_interval = {'15m': 15, '45m': 45, '90m': 90, '4h': 4*60, 'daily': 24*60}
        for curInterval in ('15m', '45m', '90m', '4h', 'daily'):
            if sickbeard.CHECK_PROPERS_INTERVAL == curInterval:
                self.updateInterval = datetime.timedelta(minutes = check_propers_interval[curInterval])

    def run(self, force=False):

        if not sickbeard.DOWNLOAD_PROPERS:
            return

        # look for propers every night at 1 AM
        updateTime = datetime.time(hour=1)

        logger.log(u"Checking proper time", logger.DEBUG)

        hourDiff = datetime.datetime.today().time().hour - updateTime.hour
        dayDiff = (datetime.date.today() - self._get_lastProperSearch()).days

        if sickbeard.CHECK_PROPERS_INTERVAL == "daily" and not force:
            # if it's less than an interval after the update time then do an update
            if not (hourDiff >= 0 and hourDiff < self.updateInterval.seconds / 3600 or dayDiff >= 1):
                return

        logger.log(u"Beginning the search for new propers")

        self.amActive = True

        propers = self._getProperList()

        if propers:
            self._downloadPropers(propers)

        self._set_lastProperSearch(datetime.datetime.today().toordinal())

        msg = u"Completed the search for new propers, next check "
        if sickbeard.CHECK_PROPERS_INTERVAL == "daily":
            logger.log(u"%sat 1am tomorrow" % msg)
        else:
            logger.log(u"%sin ~%s" % (msg, sickbeard.CHECK_PROPERS_INTERVAL))

        self.amActive = False

    def _getProperList(self):
        propers = {}

        # for each provider get a list of the
        origThreadName = threading.currentThread().name
        providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()]
        for curProvider in providers:
            threading.currentThread().name = origThreadName + " :: [" + curProvider.name + "]"

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

            logger.log(u"Searching for any new PROPER releases from " + curProvider.name)
            try:
                curPropers = curProvider.findPropers(search_date)
            except exceptions.AuthException, e:
                logger.log(u"Authentication error: " + ex(e), logger.ERROR)
                continue

            # if they haven't been added by a different provider than add the proper to the list
            for x in curPropers:
                name = self._genericName(x.name)
                if not name in propers:
                    logger.log(u"Found new proper: " + x.name, logger.DEBUG)
                    x.provider = curProvider
                    propers[name] = x

        # reset thread name back to original
        threading.currentThread().name = 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:
            in_cache = False

            try:
                myParser = NameParser(False)
                parse_result = myParser.parse(curProper.name)
            except InvalidNameException:
                logger.log(u"Unable to parse the filename " + curProper.name + " into a valid episode", logger.DEBUG)
                continue

            if not parse_result.series_name:
                continue

            cacheResult = sickbeard.name_cache.retrieveNameFromCache(parse_result.series_name)
            if cacheResult:
                in_cache = True
                curProper.indexerid = int(cacheResult)
            elif cacheResult == 0:
                return None

            if not curProper.indexerid:
                showResult = helpers.searchDBForShow(parse_result.series_name)
                if showResult:
                    curProper.indexerid = int(showResult[0])

            if not curProper.indexerid:
                for curShow in sickbeard.showList:
                    if show_name_helpers.isGoodResult(curProper.name, curShow, False):
                        curProper.indexerid = curShow.indexerid
                        break

            showObj = None
            if curProper.indexerid:
                showObj = helpers.findCertainShow(sickbeard.showList, curProper.indexerid)

            if not showObj:
                sickbeard.name_cache.addNameToCache(parse_result.series_name, 0)
                continue

            if not in_cache:
                sickbeard.name_cache.addNameToCache(parse_result.series_name, curProper.indexerid)

            # scene numbering -> indexer numbering
            parse_result = parse_result.convert(showObj)

            if not parse_result.episode_numbers:
                logger.log(
                    u"Ignoring " + curProper.name + " because it's for a full season rather than specific episode",
                    logger.DEBUG)
                continue

            # populate our Proper instance
            if parse_result.air_by_date or parse_result.sports:
                curProper.season = -1
                curProper.episode = parse_result.air_date or parse_result.sports_event_date
            else:
                curProper.season = parse_result.season_number if parse_result.season_number != None else 1
                curProper.episode = parse_result.episode_numbers[0]

            curProper.quality = Quality.nameQuality(curProper.name)

            # for each show in our list
            for curShow in sickbeard.showList:

                genericName = self._genericName(parse_result.series_name)

                # get the scene name masks
                sceneNames = set(show_name_helpers.makeSceneShowSearchStrings(curShow))

                # for each scene name mask
                for curSceneName in sceneNames:

                    # if it matches
                    if genericName == self._genericName(curSceneName):
                        logger.log(
                            u"Successful match! Result " + parse_result.series_name + " matched to show " + curShow.name,
                            logger.DEBUG)

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

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

                        # since we found it, break out
                        break

                # if we found something in the inner for loop break out of this one
                if curProper.indexerid != -1:
                    break

            if not show_name_helpers.filterBadReleases(curProper.name):
                logger.log(u"Proper " + curProper.name + " isn't a valid scene release that we want, igoring it",
                           logger.DEBUG)
                continue

            showObj = helpers.findCertainShow(sickbeard.showList, curProper.indexerid)
            if not showObj:
                logger.log(u"Unable to find the show with indexerID " + str(curProper.indexerid), logger.ERROR)
                continue

            if showObj.rls_ignore_words and search.filter_release_name(curProper.name, showObj.rls_ignore_words):
                logger.log(u"Ignoring " + curProper.name + " based on ignored words filter: " + showObj.rls_ignore_words,
                           logger.MESSAGE)
                continue

            if showObj.rls_require_words and not search.filter_release_name(curProper.name, showObj.rls_require_words):
                logger.log(u"Ignoring " + curProper.name + " based on required words filter: " + showObj.rls_require_words,
                           logger.MESSAGE)
                continue

            # if we have an air-by-date show then get the real season/episode numbers
            if (parse_result.air_by_date or parse_result.sports_event_date) and curProper.indexerid:
                logger.log(
                    u"Looks like this is an air-by-date or sports show, attempting to convert the date to season/episode",
                    logger.DEBUG)
                airdate = curProper.episode.toordinal()
                myDB = db.DBConnection()
                sql_result = myDB.select(
                    "SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?",
                    [curProper.indexerid, curProper.indexer, airdate])

                if sql_result:
                    curProper.season = int(sql_result[0][0])
                    curProper.episodes = [int(sql_result[0][1])]
                else:
                    logger.log(u"Unable to find episode with date " + str(
                        curProper.episode) + " for show " + parse_result.series_name + ", skipping", logger.WARNING)
                    continue

            # check if we actually want this proper (if it's the right quality)
            sqlResults = db.DBConnection().select(
                "SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?",
                [curProper.indexerid, curProper.season, curProper.episode])
            if not sqlResults:
                continue
            oldStatus, oldQuality = Quality.splitCompositeStatus(int(sqlResults[0]["status"]))

            # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones)
            if oldStatus not in (DOWNLOADED, SNATCHED) or oldQuality != curProper.quality:
                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 curProper.indexerid != -1 and (curProper.indexerid, curProper.season, curProper.episode) not in map(
                    operator.attrgetter('indexerid', 'season', 'episode'), finalPropers):
                logger.log(u"Found a proper that we need: " + str(curProper.name))
                finalPropers.append(curProper)

        return finalPropers
Example #5
0
def _getProperList():
    propers = {}

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

    # for each provider get a list of the
    origThreadName = threading.currentThread().name
    providers = [
        x for x in sickbeard.providers.sortedProviderList() if x.is_active()
    ]
    for curProvider in providers:
        threading.currentThread(
        ).name = origThreadName + ' :: [' + curProvider.name + ']'

        logger.log(u'Searching for any new PROPER releases from ' +
                   curProvider.name)

        try:
            curPropers = curProvider.find_propers(search_date)
        except exceptions.AuthException as e:
            logger.log(u'Authentication error: ' + ex(e), logger.ERROR)
            continue
        except Exception as e:
            logger.log(
                u'Error while searching ' + curProvider.name + ', skipping: ' +
                ex(e), logger.ERROR)
            logger.log(traceback.format_exc(), logger.DEBUG)
            continue
        finally:
            threading.currentThread().name = origThreadName

        # if they haven't been added by a different provider than add the proper to the list
        for x in curPropers:
            name = _genericName(x.name)
            if not name in propers:
                logger.log(u'Found new proper: ' + x.name, logger.DEBUG)
                x.provider = curProvider
                propers[name] = x

    # 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:
            logger.log(
                u'Unable to parse the filename ' + curProper.name +
                ' into a valid episode', logger.DEBUG)
            continue
        except InvalidShowException:
            logger.log(
                u'Unable to parse the filename ' + curProper.name +
                ' into a valid show', logger.DEBUG)
            continue

        if not parse_result.series_name:
            continue

        if not parse_result.episode_numbers:
            logger.log(
                u'Ignoring ' + curProper.name +
                ' because it\'s for a full season rather than specific episode',
                logger.DEBUG)
            continue

        logger.log(
            u'Successful match! Result ' + parse_result.original_name +
            ' matched to show ' + parse_result.show.name, logger.DEBUG)

        # 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.season = parse_result.season_number if parse_result.season_number != 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)

        # only get anime proper if it has release group and version
        if parse_result.is_anime:
            if not curProper.release_group and curProper.version == -1:
                logger.log(
                    u'Proper ' + curProper.name +
                    ' doesn\'t have a release group and version, ignoring it',
                    logger.DEBUG)
                continue

        if not show_name_helpers.filterBadReleases(curProper.name,
                                                   parse=False):
            logger.log(
                u'Proper ' + curProper.name +
                ' isn\'t a valid scene release that we want, ignoring it',
                logger.DEBUG)
            continue

        if parse_result.show.rls_ignore_words and search.filter_release_name(
                curProper.name, parse_result.show.rls_ignore_words):
            logger.log(
                u'Ignoring ' + curProper.name +
                ' based on ignored words filter: ' +
                parse_result.show.rls_ignore_words, logger.MESSAGE)
            continue

        if parse_result.show.rls_require_words and not search.filter_release_name(
                curProper.name, parse_result.show.rls_require_words):
            logger.log(
                u'Ignoring ' + curProper.name +
                ' based on required words filter: ' +
                parse_result.show.rls_require_words, logger.MESSAGE)
            continue

        # check if we actually want this proper (if it's the right quality)
        myDB = db.DBConnection()
        sqlResults = myDB.select(
            'SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?',
            [curProper.indexerid, curProper.season, curProper.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 != curProper.quality:
            continue

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

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

            if oldVersion > -1 and oldVersion < curProper.version:
                logger.log('Found new anime v' + str(curProper.version) +
                           ' to replace existing v' + str(oldVersion))
            else:
                continue

            if oldRelease_group != curProper.release_group:
                logger.log('Skipping proper from release group: ' +
                           curProper.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 curProper.indexerid != -1 and (curProper.indexerid,
                                          curProper.season,
                                          curProper.episode) not in map(
                                              operator.attrgetter(
                                                  'indexerid', 'season',
                                                  'episode'), finalPropers):
            logger.log(u'Found a proper that we need: ' + str(curProper.name))
            finalPropers.append(curProper)

    return finalPropers
Example #6
0
def _getProperList():
    propers = {}

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

    # for each provider get a list of the
    origThreadName = threading.currentThread().name
    providers = [x for x in sickbeard.providers.sortedProviderList() if x.is_active()]
    for curProvider in providers:
        threading.currentThread().name = origThreadName + ' :: [' + curProvider.name + ']'

        logger.log(u'Searching for any new PROPER releases from ' + curProvider.name)

        try:
            curPropers = curProvider.find_propers(search_date)
        except exceptions.AuthException as e:
            logger.log(u'Authentication error: ' + ex(e), logger.ERROR)
            continue
        except Exception as e:
            logger.log(u'Error while searching ' + curProvider.name + ', skipping: ' + ex(e), logger.ERROR)
            logger.log(traceback.format_exc(), logger.DEBUG)
            continue
        finally:
            threading.currentThread().name = origThreadName

        # if they haven't been added by a different provider than add the proper to the list
        for x in curPropers:
            name = _genericName(x.name)
            if not name in propers:
                logger.log(u'Found new proper: ' + x.name, logger.DEBUG)
                x.provider = curProvider
                propers[name] = x

    # 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:
            logger.log(u'Unable to parse the filename ' + curProper.name + ' into a valid episode', logger.DEBUG)
            continue
        except InvalidShowException:
            logger.log(u'Unable to parse the filename ' + curProper.name + ' into a valid show', logger.DEBUG)
            continue

        if not parse_result.series_name:
            continue

        if not parse_result.episode_numbers:
            logger.log(
                u'Ignoring ' + curProper.name + ' because it\'s for a full season rather than specific episode',
                logger.DEBUG)
            continue

        logger.log(
            u'Successful match! Result ' + parse_result.original_name + ' matched to show ' + parse_result.show.name,
            logger.DEBUG)

        # 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.season = parse_result.season_number if parse_result.season_number != 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)

        # only get anime proper if it has release group and version
        if parse_result.is_anime:
            if not curProper.release_group and curProper.version == -1:
                logger.log(u'Proper ' + curProper.name + ' doesn\'t have a release group and version, ignoring it',
                           logger.DEBUG)
                continue

        if not show_name_helpers.filterBadReleases(curProper.name, parse=False):
            logger.log(u'Proper ' + curProper.name + ' isn\'t a valid scene release that we want, ignoring it',
                       logger.DEBUG)
            continue

        if parse_result.show.rls_ignore_words and search.filter_release_name(curProper.name,
                                                                             parse_result.show.rls_ignore_words):
            logger.log(
                u'Ignoring ' + curProper.name + ' based on ignored words filter: ' + parse_result.show.rls_ignore_words,
                logger.MESSAGE)
            continue

        if parse_result.show.rls_require_words and not search.filter_release_name(curProper.name,
                                                                                  parse_result.show.rls_require_words):
            logger.log(
                u'Ignoring ' + curProper.name + ' based on required words filter: ' + parse_result.show.rls_require_words,
                logger.MESSAGE)
            continue

        # check if we actually want this proper (if it's the right quality)
        myDB = db.DBConnection()
        sqlResults = myDB.select('SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?',
                                 [curProper.indexerid, curProper.season, curProper.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 != curProper.quality:
            continue

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

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

            if oldVersion > -1 and oldVersion < curProper.version:
                logger.log('Found new anime v' + str(curProper.version) + ' to replace existing v' + str(oldVersion))
            else:
                continue

            if oldRelease_group != curProper.release_group:
                logger.log('Skipping proper from release group: ' + curProper.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 curProper.indexerid != -1 and (curProper.indexerid, curProper.season, curProper.episode) not in map(
                operator.attrgetter('indexerid', 'season', 'episode'), finalPropers):
            logger.log(u'Found a proper that we need: ' + str(curProper.name))
            finalPropers.append(curProper)

    return finalPropers