Beispiel #1
0
    def findEpisode (self, episode, manualSearch=False):

        self._checkAuth()

        logger.log(u"Searching "+self.name+" for " + episode.prettyName(True))

        self.cache.updateCache()
        results = self.cache.searchCache(episode, manualSearch)
        logger.log(u"Cache results: "+str(results), logger.DEBUG)

        # if we got some results then use them no matter what.
        # OR
        # return anyway unless we're doing a manual search
        if results or not manualSearch:
            return results

        itemList = []

        for cur_search_string in self._get_episode_search_strings(episode):
            itemList += self._doSearch(cur_search_string)

        for item in itemList:

            title = item.findtext('title')
            url = item.findtext('link').replace('&','&')

            # parse the file name
            try:
                myParser = FileParser(title)
                epInfo = myParser.parse()
            except tvnamer_exceptions.InvalidFilename:
                logger.log(u"Unable to parse the filename "+title+" into a valid episode", logger.WARNING)
                continue

            if episode.show.is_air_by_date:
                if epInfo.episodenumbers[0] != episode.airdate:
                    logger.log("Episode "+title+" didn't air on "+str(episode.airdate)+", skipping it", logger.DEBUG)
                    continue
            elif epInfo.seasonnumber != episode.season or episode.episode not in epInfo.episodenumbers:
                logger.log("Episode "+title+" isn't "+str(episode.season)+"x"+str(episode.episode)+", skipping it", logger.DEBUG)
                continue

            quality = self.getQuality(item)

            if not episode.show.wantEpisode(episode.season, episode.episode, quality, manualSearch):
                logger.log(u"Ignoring result "+title+" because we don't want an episode that is "+Quality.qualityStrings[quality], logger.DEBUG)
                continue

            logger.log(u"Found result " + title + " at " + url, logger.DEBUG)

            result = self.getResult([episode])
            result.url = url
            result.name = title
            result.quality = quality

            results.append(result)

        return results
Beispiel #2
0
def processFile(fileName, downloadDir=None, nzbName=None):

    returnStr = ''

    folderName = None
    if downloadDir != None:
        folderName = downloadDir.split(os.path.sep)[-1]
    
    returnStr += logHelper("Processing file "+fileName+" (with folder name "+str(folderName)+" and NZB name "+str(nzbName)+")", logger.DEBUG)

    finalNameList = []

    for curName in (fileName, folderName, nzbName):
        if curName != None:
            for curSceneName in helpers.sceneToNormalShowNames(curName):
                if curSceneName not in finalNameList:
                    finalNameList.append(curSceneName)

    showResults = None
    result = None
    
    for curName in finalNameList:
    
        try:
            returnStr += logHelper("Attempting to parse name "+curName, logger.DEBUG)
            myParser = FileParser(curName)
            result = myParser.parse()
        except tvnamer_exceptions.InvalidFilename:
            returnStr += logHelper("Unable to parse the filename "+curName+" into a valid episode", logger.DEBUG)
            continue

        if not result.seriesname:
            returnStr += logHelper("Filename "+curName+" has no series name, unable to use this name for processing", logger.DEBUG)
            continue

        try:
            t = tvdb_api.Tvdb(custom_ui=classes.ShowListUI, **sickbeard.TVDB_API_PARMS)
            showObj = t[result.seriesname]
            showInfo = (int(showObj["id"]), showObj["seriesname"])
        except (tvdb_exceptions.tvdb_exception, IOError), e:

            returnStr += logHelper("TVDB didn't respond, trying to look up the show in the DB instead: "+str(e), logger.DEBUG)

            showInfo = helpers.searchDBForShow(result.seriesname)
            
        # if we didn't get anything from TVDB or the DB then try the next option
        if showInfo == None:
            continue

        # find the show in the showlist
        try:
            showResults = helpers.findCertainShow(sickbeard.showList, showInfo[0])
        except exceptions.MultipleShowObjectsException:
            raise #TODO: later I'll just log this, for now I want to know about it ASAP
        
        if showResults != None:
            returnStr += logHelper("Found the show in our list, continuing", logger.DEBUG)
            break
Beispiel #3
0
	def makeEpFromFile(self, file):

		if not os.path.isfile(file):
			logger.log(str(self.tvdbid) + ": That isn't even a real file dude... " + file)
			return None

		logger.log(str(self.tvdbid) + ": Creating episode object from " + file, logger.DEBUG)

		try:
			myParser = FileParser(file)
			epInfo = myParser.parse()
		except tvnamer_exceptions.InvalidFilename:
			logger.log("Unable to parse the filename "+file+" into a valid episode", logger.ERROR)
			return None

		# for now lets assume that any episode in the show dir belongs to that show
		season = epInfo.seasonnumber
		rootEp = None

		for curEp in epInfo.episodenumber:

			episode = int(curEp)
			
			logger.log(str(self.tvdbid) + ": " + file + " parsed to " + self.name + " " + str(season) + "x" + str(episode), logger.DEBUG)

			curEp = self.getEpisode(season, episode)
			
			if curEp == None:
				try:
					curEp = self.getEpisode(season, episode, file)
				except exceptions.EpisodeNotFoundException:
					logger.log(str(self.tvdbid) + ": Unable to figure out what this file is, skipping", logger.ERROR)
					continue
			else:
				with curEp.lock:
					curEp.location = file
					curEp.checkForMetaFiles()
					
			if rootEp == None:
				rootEp = curEp
			else:
				rootEp.relatedEps.append(curEp)

			if sickbeard.helpers.isMediaFile(file):
				with curEp.lock:
					curEp.status = DOWNLOADED
					logger.log("STATUS: we have an associated file, so setting the status to DOWNLOADED/" + str(DOWNLOADED), logger.DEBUG)
						
			with curEp.lock:
				curEp.saveToDB()
				
		# creating metafiles on the root should be good enough
		if rootEp != None:
			with rootEp.lock:
				rootEp.createMetaFiles()

		return None
Beispiel #4
0
def findSeasonResults(show, season):
	
	itemList = []
	results = {}

	for curString in helpers.makeSceneSeasonSearchString(show, season, "nzbmatrix"):
		itemList += _doSearch(curString)

	for item in itemList:

		title = item.findtext('title')
		url = item.findtext('link')
		
		quality = Quality.nameQuality(title)
		
		# parse the file name
		try:
			myParser = FileParser(title)
			epInfo = myParser.parse()
		except tvnamer_exceptions.InvalidFilename:
			logger.log("Unable to parse the filename "+title+" into a valid episode", logger.ERROR)
			continue
		
		
		if epInfo.seasonnumber != season:
			logger.log("The result "+title+" doesn't seem to be a valid episode for season "+str(season)+", ignoring")
			continue

		# make sure we want the episode
		wantEp = True
		for epNo in epInfo.episodenumbers:
			if not show.wantEpisode(season, epNo, quality):
				logger.log("Ignoring result "+title+" because we don't want an episode that is "+Quality.qualityStrings[quality], logger.DEBUG)
				wantEp = False
				break
		if not wantEp:
			continue
		
		logger.log("Found result " + title + " at " + url, logger.DEBUG)
		
		# make a result object
		epNum = epInfo.episodenumbers[0]
		epObj = show.getEpisode(season, epNum)
		
		result = classes.NZBSearchResult(epObj)
		result.provider = providerName.lower()
		result.url = url
		result.extraInfo = [title]
		result.quality = quality
	
		if epNum in results:
			results[epNum].append(result)
		else:
			results[epNum] = [result]
		
	return results
Beispiel #5
0
    def findEpisode(self, episode, manualSearch=False):

        nzbResults = generic.NZBProvider.findEpisode(self, episode, manualSearch)

        # if we got some results then use them no matter what.
        # OR
        # return anyway unless we're doing a manual search
        if nzbResults or not manualSearch:
            return nzbResults

        sceneSearchStrings = set(sceneHelpers.makeSceneSearchString(episode))

        results = []

        # search for all show names and episode numbers like ("a","b","c") in a single search
        nzbMatrixSearchString = '("' + '","'.join(sceneSearchStrings) + '")'
        itemList = self._doSearch(nzbMatrixSearchString)

        for item in itemList:

            title = item.findtext("title")
            url = item.findtext("link").replace("&", "&")

            # parse the file name
            try:
                myParser = FileParser(title)
                epInfo = myParser.parse()
            except tvnamer_exceptions.InvalidFilename:
                logger.log(u"Unable to parse the name " + title + " into a valid episode", logger.WARNING)
                continue

            quality = self.getQuality(item)

            season = epInfo.seasonnumber if epInfo.seasonnumber != None else 1

            if not episode.show.wantEpisode(season, episode.episode, quality, manualSearch):
                logger.log(
                    u"Ignoring result "
                    + title
                    + " because we don't want an episode that is "
                    + Quality.qualityStrings[quality],
                    logger.DEBUG,
                )
                continue

            logger.log(u"Found result " + title + " at " + url, logger.DEBUG)

            result = self.getResult([episode])
            result.url = url
            result.name = title
            result.quality = quality

            results.append(result)

        return results
Beispiel #6
0
def findEpisode (episode, manualSearch=False):

	logger.log("Searching NZBMatrix for " + episode.prettyName(True))

	myCache = NZBMatrixCache()
	myCache.updateCache()
	nzbResults = myCache.searchCache(episode)
	logger.log("Cache results: "+str(nzbResults), logger.DEBUG)

	# if we got some results then use them no matter what.
	# OR
	# return anyway unless we're doing a manual search
	if nzbResults or not manualSearch:
		return nzbResults
	
	sceneSearchStrings = set(sceneHelpers.makeSceneSearchString(episode))
	
	results = []

	# search for all show names and episode numbers like ("a","b","c") in a single search
	nzbMatrixSearchString = '("' + '","'.join(sceneSearchStrings) + '")'
	itemList = _doSearch(nzbMatrixSearchString)

	for item in itemList:
		
		title = item.findtext('title')
		url = item.findtext('link').replace('&','&')
		
		# parse the file name
		try:
			myParser = FileParser(title)
			epInfo = myParser.parse()
		except tvnamer_exceptions.InvalidFilename:
			logger.log("Unable to parse the filename "+title+" into a valid episode", logger.ERROR)
			continue
		
		quality = Quality.nameQuality(title)
		
		if not episode.show.wantEpisode(episode.season, episode.episode, quality, manualSearch):
			logger.log("Ignoring result "+title+" because we don't want an episode that is "+Quality.qualityStrings[quality], logger.DEBUG)
			continue
		
		logger.log("Found result " + title + " at " + url, logger.DEBUG)
		
		result = classes.NZBSearchResult([episode])
		result.provider = providerName.lower()
		result.url = url
		result.name = title
		result.quality = quality
		
		results.append(result)
		
	return results
Beispiel #7
0
def filterBadReleases(name):

    try:
        fp = FileParser(name)
        epInfo = fp.parse()
    except tvnamer_exceptions.InvalidFilename:
        logger.log("Unable to parse the filename "+name+" into a valid episode", logger.WARNING)
        return False
    
    # if there's no info after the season info then assume it's fine
    if not epInfo.episodename:
        return True
    
    # if any of the bad strings are in the name then say no
    for x in resultFilters:
        if re.search('(^|[\W_])'+x+'($|[\W_])', epInfo.episodename, re.I):
            logger.log("Invalid scene release: "+name+" contains "+x+", ignoring it", logger.DEBUG)
            return False

    return True
Beispiel #8
0
def splitResult(result):
    
    fileObj = urllib.urlopen(result.url)
    
    # parse the season ep name
    try:
        fp = FileParser(result.name)
        epInfo = fp.parse()
    except tvnamer_exceptions.InvalidFilename:
        logger.log("Unable to parse the filename "+result.name+" into a valid episode", logger.WARNING)
        return False

    # bust it up
    season = epInfo.seasonnumber
    separateNZBs, xmlns = getSeasonNZBs(result.name, fileObj, season)

    resultList = []
    
    for newNZB in separateNZBs:

        logger.log("Split out "+newNZB+" from "+result.name, logger.DEBUG)

        # parse the name
        try:
            fp = FileParser(newNZB)
            epInfo = fp.parse()
        except tvnamer_exceptions.InvalidFilename:
            logger.log("Unable to parse the filename "+newNZB+" into a valid episode", logger.WARNING)
            return False

        # make sure the result is sane
        if epInfo.seasonnumber != season:
            logger.log("Found "+newNZB+" inside "+result.name+" but it doesn't seem to belong to the same season, ignoring it", logger.WARNING)
            continue
        elif len(epInfo.episodenumbers) == 0:
            logger.log("Found "+newNZB+" inside "+result.name+" but it doesn't seem to be a valid episode NZB, ignoring it", logger.WARNING)
            continue

        wantEp = True
        for epNo in epInfo.episodenumbers:
            if epNo == -1:
                continue
            if not result.extraInfo[0].wantEpisode(season, epNo, result.quality):
                logger.log("Ignoring result "+newNZB+" because we don't want an episode that is "+Quality.qualityStrings[result.quality], logger.DEBUG)
                wantEp = False
                break
        if not wantEp:
            continue

        # get all the associated episode objects
        epObjList = []
        for curEp in epInfo.episodenumbers:
            epObjList.append(result.extraInfo[0].getEpisode(season, curEp))

        # make a result
        curResult = classes.NZBDataSearchResult(epObjList)
        curResult.name = newNZB
        curResult.provider = result.provider
        curResult.quality = result.quality
        curResult.extraInfo = [createNZBString(separateNZBs[newNZB], xmlns)]

        resultList.append(curResult)

    return resultList
Beispiel #9
0
    def _addCacheEntry(self, name, url, season=None, episodes=None, tvdb_id=0, tvrage_id=0, quality=None, extraNames=[]):
        
        myDB = self._getDB()
        
        epInfo = None
        
        # if we don't have complete info then parse the filename to get it
        for curName in [name] + extraNames:
            try:
                myParser = FileParser(curName)
                epInfo = myParser.parse()
            except tvnamer_exceptions.InvalidFilename:
                logger.log("Unable to parse the filename "+curName+" into a valid episode", logger.DEBUG)
                continue
        
        if not epInfo:
            logger.log("Giving up because I'm unable to figure out what show/etc this is: "+name, logger.DEBUG)
            return False
        
        if not epInfo.seriesname:
            logger.log("No series name retrieved from "+name+", unable to cache it", logger.DEBUG)
            return False

        # if we need tvdb_id or tvrage_id then search the DB for them
        if not tvdb_id or not tvrage_id:
            
            # if we have only the tvdb_id, use the database
            if tvdb_id:
                showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id)
                if showObj:
                    tvrage_id = showObj.tvrid
                else:
                    logger.log("We were given a TVDB id "+str(tvdb_id)+" but it doesn't match a show we have in our list, so leaving tvrage_id empty", logger.DEBUG)
                    tvrage_id = 0 
            
            # if we have only a tvrage_id then use the database
            elif tvrage_id:
                showObj = helpers.findCertainTVRageShow(sickbeard.showList, tvrage_id)
                if showObj:
                    tvdb_id = showObj.tvdbid
                else:
                    logger.log("We were given a TVRage id "+str(tvrage_id)+" but it doesn't match a show we have in our list, so leaving tvdb_id empty", logger.DEBUG)
                    tvdb_id = 0 
            
            # if they're both empty then fill out as much info as possible by searching the show name
            else:    

                showResult = helpers.searchDBForShow(epInfo.seriesname)
                if showResult:
                    logger.log(epInfo.seriesname+" was found to be show "+showResult[1]+" ("+str(showResult[0])+") in our DB.", logger.DEBUG)
                    tvdb_id = showResult[0]
                    showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id)
                    if not showObj:
                        logger.log("This should never have happened, post a bug about this!", logger.ERROR)
                        raise Exception("BAD STUFF HAPPENED")
                    tvrage_id = showObj.tvrid
            
            
        if not season:
            season = epInfo.seasonnumber
        if not episodes:
            episodes = epInfo.episodenumbers

        # if we have an air-by-date show then get the real season/episode numbers
        if season == -1 and tvdb_id:
            try:
                t = tvdb_api.Tvdb(**sickbeard.TVDB_API_PARMS)
                epObj = t[tvdb_id].airedOn(episodes[0])[0]
                season = int(epObj["seasonnumber"])
                episodes = [int(epObj["episodenumber"])]
            except tvdb_exceptions.tvdb_episodenotfound, e:
                logger.log("Unable to find episode with date "+str(episodes[0])+" for show "+epInfo.seriesname+", skipping", logger.WARNING)
                return False
Beispiel #10
0
    def _getProperList(self):
    
        propers = {}
        
        # for each provider get a list of the propers
        for curProvider in providers.sortedProviderList():
            
            if not curProvider.isActive():
                continue

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

            logger.log("Searching for any new PROPER releases from "+curProvider.name)
            curPropers = curProvider.findPropers(date)
            
            # 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("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 = FileParser(curProper.name)
                epInfo = myParser.parse()
            except tvnamer_exceptions.InvalidFilename:
                logger.log("Unable to parse the filename "+curProper.name+" into a valid episode", logger.ERROR)
                continue
    
            if not epInfo.episodenumbers:
                logger.log("Ignoring "+curProper.name+" because it's for a full season rather than specific episode", logger.DEBUG)
                continue
    
            # populate our Proper instance
            curProper.season = epInfo.seasonnumber
            curProper.episode = epInfo.episodenumbers[0]
            curProper.quality = Quality.nameQuality(curProper.name)
    
            # for each show in our list
            for curShow in sickbeard.showList:
        
                genericName = self._genericName(epInfo.seriesname)
        
                # get the scene name masks
                sceneNames = set(sceneHelpers.makeSceneShowSearchStrings(curShow))
        
                # for each scene name mask
                for curSceneName in sceneNames:
        
                    # if it matches
                    if genericName == self._genericName(curSceneName):
                        logger.log("Successful match! Result "+epInfo.seriesname+" 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 we have an air-by-date show then get the real season/episode numbers
            if curProper.season == -1 and curProper.tvdbid:
                try:
                    t = tvdb_api.Tvdb(**sickbeard.TVDB_API_PARMS)
                    epObj = t[curProper.tvdbid].airedOn(curProper.episode)[0]
                    season = int(epObj["seasonnumber"])
                    episodes = [int(epObj["episodenumber"])]
                except tvdb_exceptions.tvdb_episodenotfound, e:
                    logger.log("Unable to find episode with date "+str(curProper.episode)+" for show "+epInfo.seriesname+", 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("Found a proper that we need: "+str(curProper.name))
                finalPropers.append(curProper)
def processFile(fileName, downloadDir=None, nzbName=None, multi_file=False):

    returnStr = ''

    folderName = None
    if downloadDir != None:
        folderName = downloadDir.split(os.path.sep)[-1]

    returnStr += logHelper(u"Processing file "+fileName+" (with folder name "+str(folderName)+" and NZB name "+str(nzbName)+")", logger.DEBUG)

    finalNameList = []

    for curName in (fileName, folderName, nzbName):
        if curName != None:
            for curSceneName in sceneHelpers.sceneToNormalShowNames(curName):
                if curSceneName not in finalNameList:
                    finalNameList.append(curSceneName)

    showResults = None
    result = None

    tvdb_id = None
    season = None
    episodes = []

    # first try looking up every name in our history
    for curName in finalNameList:

        historyResult = findInHistory(curName)
        if historyResult:
            returnStr += logHelper(u"Result from history: "+str(historyResult)+" from "+curName, logger.DEBUG)
            (tvdb_id, season, episodes) = historyResult
            showResults = helpers.findCertainShow(sickbeard.showList, tvdb_id)
            break

    # if we're parsing a multi-file folder then the folder name doesn't reflect the correct episode so ignore it
    if multi_file and episodes:
        returnStr += logHelper(u"Multi-file dir "+downloadDir+" doesn't reflect all episode names, only using name & season", logger.DEBUG)
        episodes = []

    # if that didn't work then try manually parsing and searching them on TVDB
    for curName in finalNameList:

        # if we already have the info from the history then don't bother with this
        if tvdb_id != None and season != None and episodes != []:
            break

        # if we're doing a multi-file dir and we already got the tvdb_id/season but no episodes then assume it's right and carry it forward 
        # otherwise, reset it every time
        if not (tvdb_id and season and not episodes and multi_file):
            tvdb_id = None
            season = None
        episodes = []

        try:
            returnStr += logHelper(u"Attempting to parse name "+curName, logger.DEBUG)
            myParser = FileParser(curName)
            result = myParser.parse()

            season = result.seasonnumber if result.seasonnumber != None else 1
            episodes = result.episodenumbers

            returnStr += logHelper(u"Ended up with season "+str(season)+" and episodes "+str(episodes), logger.DEBUG)

        except tvnamer_exceptions.InvalidFilename:
            returnStr += logHelper(u"Unable to parse the filename "+curName+" into a valid episode", logger.DEBUG)
            continue

        if not result.seriesname:
            returnStr += logHelper(u"Filename "+curName+" has no series name, unable to use this name for processing", logger.DEBUG)
            continue

        if not episodes:
            returnStr += logHelper(u"Unable to find an episode number in the filename "+curName+", skipping", logger.DEBUG)
            continue

        # reverse-lookup the scene exceptions
        returnStr += logHelper(u"Checking scene exceptions for "+result.seriesname, logger.DEBUG)
        sceneID = None
        for exceptionID in sceneExceptions:
            for curException in sceneExceptions[exceptionID]:
                if result.seriesname == curException:
                    sceneID = exceptionID
                    break
            if sceneID:
                returnStr += logHelper(u"Scene exception lookup got tvdb id "+str(sceneID)+", using that", logger.DEBUG)
                break

        if sceneID:
            tvdb_id = sceneID

        showObj = None
        try:
            t = tvdb_api.Tvdb(custom_ui=classes.ShowListUI, **sickbeard.TVDB_API_PARMS)

            # get the tvdb object from either the scene exception ID or the series name
            if tvdb_id:
                returnStr += logHelper(u"Looking up ID "+str(tvdb_id)+" on TVDB", logger.DEBUG)
                showObj = t[tvdb_id]
            else:
                returnStr += logHelper(u"Looking up name "+result.seriesname+" on TVDB", logger.DEBUG)
                showObj = t[result.seriesname]

            returnStr += logHelper(u"Got tvdb_id "+str(showObj["id"])+" and series name "+showObj["seriesname"].decode('utf-8')+" from TVDB", logger.DEBUG)

            showInfo = (int(showObj["id"]), showObj["seriesname"])

        except (tvdb_exceptions.tvdb_exception, IOError), e:

            returnStr += logHelper(u"Unable to look up show on TVDB: "+str(e).decode('utf-8'), logger.DEBUG)
            returnStr += logHelper(u"Looking up show in DB instead", logger.DEBUG)
            showInfo = helpers.searchDBForShow(result.seriesname)

        if showInfo:
            tvdb_id = showInfo[0]

        if showInfo and season == None:
            myDB = db.DBConnection()
            numseasonsSQlResult = myDB.select("SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0", [tvdb_id])
            numseasons = numseasonsSQlResult[0][0]
            if numseasons == 1 and season == None:
                returnStr += logHelper(u"Don't have a season number, but this show appears to only have 1 season, setting seasonnumber to 1...", logger.DEBUG)
                season = 1

        # if it is an air-by-date show and we successfully found it on TVDB, convert the date into a season/episode
        if season == -1 and showObj:
            returnStr += logHelper(u"Looks like this is an air-by-date show, attempting to parse...", logger.DEBUG)
            try:
                epObj = showObj.airedOn(episodes[0])[0]
                season = int(epObj["seasonnumber"])
                episodes = [int(epObj["episodenumber"])]
            except tvdb_exceptions.tvdb_episodenotfound, e:
                returnStr += logHelper(u"Unable to find episode with date "+str(episodes[0])+" for show "+showObj["seriesname"]+", skipping", logger.DEBUG)
                continue
Beispiel #12
0
def processFile(fileName, downloadDir=None, nzbName=None):

    returnStr = ''

    folderName = None
    if downloadDir != None:
        folderName = downloadDir.split(os.path.sep)[-1]
    
    returnStr += logHelper("Processing file "+fileName+" (with folder name "+str(folderName)+" and NZB name "+str(nzbName)+")", logger.DEBUG)

    finalNameList = []

    for curName in (fileName, folderName, nzbName):
        if curName != None:
            for curSceneName in sceneHelpers.sceneToNormalShowNames(curName):
                if curSceneName not in finalNameList:
                    finalNameList.append(curSceneName)

    showResults = None
    result = None
    
    tvdb_id = None
    season = None
    episodes = []
        
    # first try looking up every name in our history
    for curName in finalNameList:

        historyResult = findInHistory(curName)
        if historyResult:
            returnStr += logHelper("Result from history: "+str(historyResult)+" from "+curName, logger.DEBUG)
            (tvdb_id, season, episode) = historyResult
            episodes = [episode]
            showResults = helpers.findCertainShow(sickbeard.showList, tvdb_id)
            break

    # if that didn't work then try manually parsing and searching them on TVDB
    for curName in finalNameList:
        
        # if we already have the info from the history then don't bother with this
        if tvdb_id != None and season != None and episodes != []:
            break

        # set all search stuff to defaults so we don't carry results over from the last iteration
        tvdb_id = None
        season = None
        episodes = []
        
        try:
            returnStr += logHelper("Attempting to parse name "+curName, logger.DEBUG)
            myParser = FileParser(curName)
            result = myParser.parse()

            season = result.seasonnumber
            episodes = result.episodenumbers
            
        except tvnamer_exceptions.InvalidFilename:
            returnStr += logHelper("Unable to parse the filename "+curName+" into a valid episode", logger.DEBUG)
            continue

        if not result.seriesname:
            returnStr += logHelper("Filename "+curName+" has no series name, unable to use this name for processing", logger.DEBUG)
            continue

        if not episodes:
            returnStr += logHelper("Unable to find an episode number in the filename "+curName+", skipping", logger.DEBUG)
            continue

        # reverse-lookup the scene exceptions
        sceneID = None
        for exceptionID in sceneExceptions:
            if curName == sceneExceptions[exceptionID]:
                sceneID = exceptionID
                break

        try:
            returnStr += logHelper("Looking up name "+result.seriesname+" on TVDB", logger.DEBUG)
            t = tvdb_api.Tvdb(custom_ui=classes.ShowListUI, **sickbeard.TVDB_API_PARMS)

            # get the tvdb object from either the scene exception ID or the series name
            if sceneID:
                showObj = t[sceneID]
            else:
                showObj = t[result.seriesname]
            
            showInfo = (int(showObj["id"]), showObj["seriesname"])
        except (tvdb_exceptions.tvdb_exception, IOError), e:

            returnStr += logHelper("Unable to look up show on TVDB: "+str(e), logger.DEBUG)
            returnStr += logHelper("Looking up show in DB instead", logger.DEBUG)
            showInfo = helpers.searchDBForShow(result.seriesname)

        if showInfo:
            tvdb_id = showInfo[0]

        # if it is an air-by-date show and we successfully found it on TVDB, convert the date into a season/episode
        if season == -1 and showObj:
            try:
                epObj = showObj.airedOn(episodes[0])[0]
                season = int(epObj["seasonnumber"])
                episodes = [int(epObj["episodenumber"])]
            except tvdb_exceptions.tvdb_episodenotfound, e:
                returnStr += logHelper("Unable to find episode with date "+str(episodes[0])+" for show "+showObj["seriesname"]+", skipping", logger.DEBUG)
                continue
    def findSeasonResults(self, show, season):

        itemList = []
        results = {}

        for curString in self._get_season_search_strings(show, season):
            itemList += self._doSearch(curString)

        for item in itemList:

            title = item.findtext("title")
            url = item.findtext("link")

            quality = self.getQuality(item)

            # parse the file name
            try:
                myParser = FileParser(title)
                epInfo = myParser.parse()
            except tvnamer_exceptions.InvalidFilename:
                logger.log(u"Unable to parse the filename " + title + " into a valid episode", logger.WARNING)
                continue

            if not show.is_air_by_date:
                # this check is meaningless for non-season searches
                if (epInfo.seasonnumber != None and epInfo.seasonnumber != season) or (
                    epInfo.seasonnumber == None and season != 1
                ):
                    logger.log(
                        u"The result "
                        + title
                        + " doesn't seem to be a valid episode for season "
                        + str(season)
                        + ", ignoring"
                    )
                    continue

                # we just use the existing info for normal searches
                actual_season = season
                actual_episodes = epInfo.episodenumbers

            else:
                if epInfo.seasonnumber != -1 or len(epInfo.episodenumbers) != 1:
                    logger.log(
                        u"This is supposed to be an air-by-date search but the result "
                        + title
                        + " didn't parse as one, skipping it",
                        logger.DEBUG,
                    )
                    continue

                myDB = db.DBConnection()
                sql_results = myDB.select(
                    "SELECT season, episode FROM tv_episodes WHERE showid = ? AND airdate = ?",
                    [show.tvdbid, epInfo.episodenumbers[0].toordinal()],
                )

                if len(sql_results) != 1:
                    logger.log(
                        u"Tried to look up the date for the episode "
                        + title
                        + " but the database didn't give proper results, skipping it",
                        logger.ERROR,
                    )
                    continue

                actual_season = int(sql_results[0]["season"])
                actual_episodes = [int(sql_results[0]["episode"])]

            # make sure we want the episode
            wantEp = True
            for epNo in actual_episodes:
                if not show.wantEpisode(actual_season, epNo, quality):
                    wantEp = False
                    break

            if not wantEp:
                logger.log(
                    u"Ignoring result "
                    + title
                    + " because we don't want an episode that is "
                    + Quality.qualityStrings[quality],
                    logger.DEBUG,
                )
                continue

            logger.log(u"Found result " + title + " at " + url, logger.DEBUG)

            # make a result object
            epObj = []
            for curEp in actual_episodes:
                epObj.append(show.getEpisode(actual_season, curEp))

            result = self.getResult(epObj)
            result.url = url
            result.name = title
            result.quality = quality

            if len(epObj) == 1:
                epNum = epObj[0].episode
            elif len(epObj) > 1:
                epNum = MULTI_EP_RESULT
                logger.log(
                    u"Separating multi-episode result to check for later - result contains episodes: "
                    + str(epInfo.episodenumbers),
                    logger.DEBUG,
                )
            elif len(epObj) == 0:
                epNum = SEASON_RESULT
                result.extraInfo = [show]
                logger.log(u"Separating full season result to check for later", logger.DEBUG)

            if epNum in results:
                results[epNum].append(result)
            else:
                results[epNum] = [result]

        return results
Beispiel #14
0
	def findSeasonResults(self, show, season):

		itemList = []
		results = {}

		for curString in sceneHelpers.makeSceneSeasonSearchString(show, season, "nzbmatrix"):
			itemList += self._doSearch(curString)

		for item in itemList:

			title = item.findtext('title')
			url = item.findtext('link')

			quality = Quality.nameQuality(title)

			# parse the file name
			try:
				myParser = FileParser(title)
				epInfo = myParser.parse()
			except tvnamer_exceptions.InvalidFilename:
				logger.log(u"Unable to parse the name "+title+" into a valid episode", logger.WARNING)
				continue


			if (epInfo.seasonnumber != None and epInfo.seasonnumber != season) or (epInfo.seasonnumber == None and season != 1):
				logger.log(u"The result "+title+" doesn't seem to be a valid episode for season "+str(season)+", ignoring")
				continue

			# make sure we want the episode
			wantEp = True
			for epNo in epInfo.episodenumbers:
				if not show.wantEpisode(season, epNo, quality):
					logger.log(u"Ignoring result "+title+" because we don't want an episode that is "+Quality.qualityStrings[quality], logger.DEBUG)
					wantEp = False
					break
			if not wantEp:
				continue

			logger.log(u"Found result " + title + " at " + url, logger.DEBUG)

			# make a result object
			epObj = []
			for curEp in epInfo.episodenumbers:
				epObj.append(show.getEpisode(season, curEp))

			result = self.getResult(epObj)
			result.url = url
			result.name = title
			result.quality = quality

			if len(epObj) == 1:
				epNum = epObj[0].episode
			elif len(epObj) > 1:
				epNum = MULTI_EP_RESULT
				logger.log(u"Separating multi-episode result to check for later - result contains episodes: "+str(epInfo.episodenumbers), logger.DEBUG)
			elif len(epObj) == 0:
				epNum = SEASON_RESULT
				result.extraInfo = [show]
				logger.log(u"Separating full season result to check for later", logger.DEBUG)

			if epNum in results:
				results[epNum].append(result)
			else:
				results[epNum] = [result]

		return results
Beispiel #15
0
def doIt(downloaderDir, nzbName=None):
    
    returnStr = ""

    downloadDir = ''

    # if they passed us a real dir then assume it's the one we want
    if os.path.isdir(downloaderDir):
        downloadDir = os.path.abspath(downloaderDir)
    
    # if they've got a download dir configured then use it
    elif sickbeard.TV_DOWNLOAD_DIR != '' and os.path.isdir(sickbeard.TV_DOWNLOAD_DIR):
        downloadDir = os.path.join(sickbeard.TV_DOWNLOAD_DIR, os.path.abspath(downloaderDir).split(os.path.sep)[-1])

        returnStr += logHelper("Trying to use folder "+downloadDir, logger.DEBUG)

    # if we didn't find a real dir then quit
    if not os.path.isdir(downloadDir):
        returnStr += logHelper("Unable to figure out what folder to process. If your downloader and Sick Beard aren't on the same PC make sure you fill out your TV download dir in the config.", logger.DEBUG)
        return returnStr

    myDB = db.DBConnection()
    sqlResults = myDB.select("SELECT * FROM tv_shows")
    for sqlShow in sqlResults:
        if downloadDir.startswith(os.path.abspath(sqlShow["location"])+os.sep):
            returnStr += logHelper("You're trying to post process a show that's already been moved to its show dir", logger.ERROR)
            return returnStr

    returnStr += logHelper("Final folder name is " + downloadDir, logger.DEBUG)
    
    # TODO: check if it's failed and deal with it if it is
    if downloadDir.startswith('_FAILED_'):
        returnStr += logHelper("The directory name indicates it failed to extract, cancelling", logger.DEBUG)
        return returnStr
    
    # find the file we're dealing with
    biggest_file = findMainFile(downloadDir)
    if biggest_file == None:
        returnStr += logHelper("Unable to find the biggest file - is this really a TV download?", logger.DEBUG)
        return returnStr
        
    returnStr += logHelper("The biggest file in the dir is: " + biggest_file, logger.DEBUG)
    
    # use file name, folder name, and NZB name (in that order) to try to figure out the episode info
    result = None
    nameList = [downloadDir.split(os.path.sep)[-1], biggest_file]
    if nzbName != None:
        nameList.append(nzbName)
    
    showResults = None
    
    for curName in nameList:
    
        try:
            myParser = FileParser(curName)
            result = myParser.parse()
        except tvnamer_exceptions.InvalidFilename:
            returnStr += logHelper("Unable to parse the filename "+curName+" into a valid episode", logger.DEBUG)
            continue

        try:
            t = tvdb_api.Tvdb(custom_ui=classes.ShowListUI,
                              lastTimeout=sickbeard.LAST_TVDB_TIMEOUT,
                              **sickbeard.TVDB_API_PARMS)
            showObj = t[result.seriesname]
            showInfo = (int(showObj["id"]), showObj["seriesname"])
        except (tvdb_exceptions.tvdb_exception, IOError), e:

            returnStr += logHelper("TVDB didn't respond, trying to look up the show in the DB instead", logger.DEBUG)

            showInfo = helpers.searchDBForShow(result.seriesname)
            
        # if we didn't get anything from TVDB or the DB then try the next option
        if showInfo == None:
            continue

        # find the show in the showlist
        try:
            showResults = helpers.findCertainShow(sickbeard.showList, showInfo[0])
        except exceptions.MultipleShowObjectsException:
            raise #TODO: later I'll just log this, for now I want to know about it ASAP
        
        if showResults != None:
            returnStr += logHelper("Found the show in our list, continuing", logger.DEBUG)
            break
Beispiel #16
0
    def _getProperList(self):
    
        propers = {}
        
        # for each provider get a list of the propers
        for curProvider in providers.getAllModules():
            
            if not curProvider.isActive():
                continue

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

            logger.log("Searching for any new PROPER releases from "+curProvider.providerName)
            curPropers = curProvider.findPropers(date)
            
            # 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("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 = FileParser(curProper.name)
                epInfo = myParser.parse()
            except tvnamer_exceptions.InvalidFilename:
                logger.log("Unable to parse the filename "+curProper.name+" into a valid episode", logger.ERROR)
                continue
    
            curProper.season = epInfo.seasonnumber
            curProper.episode = epInfo.episodenumbers[0]
    
            curProper.quality = helpers.guessSceneEpisodeQuality(curProper.name)
    
            # for each show in our list
            for curShow in sickbeard.showList:
        
                genericName = self._genericName(epInfo.seriesname)
        
                # get the scene name masks
                sceneNames = set(helpers.makeSceneShowSearchStrings(curShow))
        
                # for each scene name mask
                for curSceneName in sceneNames:
        
                    # if it matches
                    if genericName == self._genericName(curSceneName):
                        logger.log("Successful match! Result "+epInfo.seriesname+" 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 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("Found a proper that we need: "+str(curProper.name))
                finalPropers.append(curProper)
        
        return finalPropers
Beispiel #17
0
        stripNS(curChild, ns)

    return element


def splitResult(result):

    try:
        urlData = helpers.getURL(result.url)
    except urllib2.URLError, e:
        logger.log(u"Unable to load url "+result.url+", can't download season NZB", logger.ERROR)
        return False

    # parse the season ep name
    try:
        fp = FileParser(result.name)
        epInfo = fp.parse()
    except tvnamer_exceptions.InvalidFilename:
        logger.log(u"Unable to parse the filename "+result.name+" into a valid episode", logger.WARNING)
        return False

    # bust it up
    season = epInfo.seasonnumber if epInfo.seasonnumber != None else 1

    separateNZBs, xmlns = getSeasonNZBs(result.name, urlData, season)

    resultList = []

    for newNZB in separateNZBs:

        logger.log(u"Split out "+newNZB+" from "+result.name, logger.DEBUG)
Beispiel #18
0
        try:
            responseSoup = etree.ElementTree(etree.XML(data))
            items = responseSoup.getiterator('item')
        except Exception, e:
            logger.log("Error trying to load Newzbin RSS feed: "+str(e), logger.ERROR)
            return results

        for item in items:

            title = item.findtext('title')
            url = item.findtext('link').replace('&','&')

            # parse the file name
            try:
                myParser = FileParser(title)
                epInfo = myParser.parse()
            except tvnamer_exceptions.InvalidFilename:
                logger.log("Unable to parse the name "+title+" into a valid episode", logger.WARNING)
                continue

            quality = self.getQuality(item)

            season = epInfo.seasonnumber if epInfo.seasonnumber != None else 1

            if not episode.show.wantEpisode(season, episode.episode, quality, manualSearch):
                logger.log("Ignoring result "+title+" because we don't want an episode that is "+Quality.qualityStrings[quality], logger.DEBUG)
                continue

            logger.log("Found result " + title + " at " + url, logger.DEBUG)
Beispiel #19
0
def processFile(fileName, downloadDir=None, nzbName=None):

    returnStr = ''

    folderName = None
    if downloadDir != None:
        folderName = downloadDir.split(os.path.sep)[-1]
    
    returnStr += logHelper("Processing file "+fileName+" (with folder name "+str(folderName)+" and NZB name "+str(nzbName)+")", logger.DEBUG)

    finalNameList = []

    for curName in (fileName, folderName, nzbName):
        if curName != None:
            for curSceneName in helpers.sceneToNormalShowNames(curName):
                if curSceneName not in finalNameList:
                    finalNameList.append(curSceneName)

    showResults = None
    result = None
    
    tvdb_id = None
    season = None
    episodes = []
        
    # first try looking up every name in our history
    for curName in finalNameList:

        historyResult = findInHistory(curName)
        if historyResult:
            returnStr += logHelper("Result from history: "+str(historyResult)+" from "+curName, logger.DEBUG)
            (tvdb_id, season, episode) = historyResult
            episodes = [episode]
            showResults = helpers.findCertainShow(sickbeard.showList, tvdb_id)
            break

    # if that didn't work then try manually parsing and searching them on TVDB
    for curName in finalNameList:
        
        # if we already have the info from the history then don't bother with this
        if tvdb_id != None and season != None and episodes != []:
            break

        # set all search stuff to defaults so we don't carry results over from the last iteration
        tvdb_id = None
        season = None
        episodes = []
        
        try:
            returnStr += logHelper("Attempting to parse name "+curName, logger.DEBUG)
            myParser = FileParser(curName)
            result = myParser.parse()
            season = result.seasonnumber
            episodes = result.episodenumbers
        except tvnamer_exceptions.InvalidFilename:
            returnStr += logHelper("Unable to parse the filename "+curName+" into a valid episode", logger.DEBUG)
            continue

        if not result.seriesname:
            returnStr += logHelper("Filename "+curName+" has no series name, unable to use this name for processing", logger.DEBUG)
            continue

        # reverse-lookup the scene exceptions
        sceneID = None
        for exceptionID in sceneExceptions:
            if curName == sceneExceptions[exceptionID]:
                sceneID = exceptionID
                break

        try:
            if result.seriesname == "CSI":
                result.seriesname = "CSI: Crime Scene Investigation"
                returnStr += logHelper("Override CSI to CSI: Crime Scene Investigation", logger.DEBUG)

            returnStr += logHelper("Looking up name "+result.seriesname+" on TVDB", logger.DEBUG)
            t = tvdb_api.Tvdb(custom_ui=classes.ShowListUI, **sickbeard.TVDB_API_PARMS)

            # get the tvdb object from either the scene exception ID or the series name
            if sceneID:
                showObj = t[sceneID]
            else:
                showObj = t[result.seriesname]
            
            showInfo = (int(showObj["id"]), showObj["seriesname"])
        except (tvdb_exceptions.tvdb_exception, IOError), e:

            returnStr += logHelper("Unable to look up show on TVDB: "+str(e), logger.DEBUG)
            returnStr += logHelper("Looking up show in DB instead", logger.DEBUG)
            showInfo = helpers.searchDBForShow(result.seriesname)

        if showInfo:
            tvdb_id = showInfo[0]


        # if we couldn't get the necessary info from either of the above methods, try the next name
        if tvdb_id == None or season == None or episodes == []:
            continue

        # find the show in the showlist
        try:
            showResults = helpers.findCertainShow(sickbeard.showList, showInfo[0])
        except exceptions.MultipleShowObjectsException:
            raise #TODO: later I'll just log this, for now I want to know about it ASAP

        if showResults != None:
            returnStr += logHelper("Found the show in our list, continuing", logger.DEBUG)
            break
Beispiel #20
0
    def _addCacheEntry(self, name, url, season=None, episodes=None, tvdb_id=0, tvrage_id=0, quality=None, extraNames=[]):
        
        myDB = self._getDB()
        
        epInfo = None
        
        # if we don't have complete info then parse the filename to get it
        for curName in [name] + extraNames:
            try:
                myParser = FileParser(curName)
                epInfo = myParser.parse()
            except tvnamer_exceptions.InvalidFilename:
                logger.log("Unable to parse the filename "+curName+" into a valid episode", logger.DEBUG)
                continue
        
        if not epInfo:
            logger.log("Giving up because I'm unable to figure out what show/etc this is: "+name, logger.DEBUG)
            return False
        
        if not epInfo.seriesname:
            logger.log("No series name retrieved from "+name+", unable to cache it", logger.DEBUG)
            return False

        # if we need tvdb_id or tvrage_id then search the DB for them
        if not tvdb_id or not tvrage_id:
            
            # if we have only the tvdb_id, use the database
            if tvdb_id:
                showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id)
                if showObj:
                    tvrage_id = showObj.tvrid
                else:
                    logger.log("We were given a TVDB id "+str(tvdb_id)+" but it doesn't match a show we have in our list, so leaving tvrage_id empty", logger.DEBUG)
                    tvrage_id = 0 
            
            # if we have only a tvrage_id then use the database
            elif tvrage_id:
                showObj = helpers.findCertainTVRageShow(sickbeard.showList, tvrage_id)
                if showObj:
                    tvdb_id = showObj.tvdbid
                else:
                    logger.log("We were given a TVRage id "+str(tvrage_id)+" but it doesn't match a show we have in our list, so leaving tvdb_id empty", logger.DEBUG)
                    tvdb_id = 0 
            
            # if they're both empty then fill out as much info as possible by searching the show name
            else:    

                showResult = helpers.searchDBForShow(epInfo.seriesname)
                if showResult:
                    logger.log(epInfo.seriesname+" was found to be show "+showResult[1]+" ("+str(showResult[0])+") in our DB.", logger.DEBUG)
                    tvdb_id = showResult[0]
                    showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id)
                    if not showObj:
                        logger.log("This should never have happened, post a bug about this!", logger.ERROR)
                        raise Exception("BAD STUFF HAPPENED")
                    tvrage_id = showObj.tvrid
            
            
        if not season:
            season = epInfo.seasonnumber
        if not episodes:
            episodes = epInfo.episodenumbers

        episodeText = "|"+"|".join(map(str, episodes))+"|"
        
        
        # get the current timestamp
        curTimestamp = int(time.mktime(datetime.datetime.today().timetuple()))
        
        if not quality:
            # if we don't know what quality it is and it looks like itouch quality, skip it
            if "itouch" in name.lower():
                return False
            elif any(x in name.lower() for x in ("720p", "1080p", "x264")):
                quality = HD
            elif any(x in name.lower() for x in ("xvid", "divx")):
                quality = SD
            else:
                logger.log("Unable to figure out the quality of "+name+", assuming SD", logger.DEBUG)
                quality = SD
        
        myDB.action("INSERT INTO "+self.providerName+" (name, season, episodes, tvrid, tvdbid, url, time, quality) VALUES (?,?,?,?,?,?,?,?)",
                    [name, season, episodeText, tvrage_id, tvdb_id, url, curTimestamp, quality])