def _analyze_name(self, name, file=True): """ Takes a name and tries to figure out a show, season, and episode from it. name: A string which we want to analyze to determine show info from (unicode) Returns a (indexer_id, season, [episodes]) tuple. The first two may be None and episodes may be [] if none were found. """ logger.log(u"Analyzing name " + repr(name)) to_return = (None, None, []) if not name: return to_return # parse the name to break it into show name, season, and episode np = NameParser(file) parse_result = np.parse(name) self._log("Parsed " + name + " into " + str(parse_result).decode('utf-8'), logger.DEBUG) if parse_result.air_by_date: season = -1 episodes = [parse_result.air_date] else: season = parse_result.season_number episodes = parse_result.episode_numbers to_return = (None, season, episodes) # do a scene reverse-lookup to get a list of all possible names name_list = show_name_helpers.sceneToNormalShowNames(parse_result.series_name) if not name_list: return (None, season, episodes) def _finalize(parse_result): self.release_group = parse_result.release_group # remember whether it's a proper if parse_result.extra_info: self.is_proper = re.search('(^|[\. _-])(proper|repack)([\. _-]|$)', parse_result.extra_info, re.I) != None # if the result is complete then remember that for later if parse_result.series_name and parse_result.season_number != None and parse_result.episode_numbers and parse_result.release_group: test_name = os.path.basename(name) if test_name == self.nzb_name: self.good_results[self.NZB_NAME] = True elif test_name == self.folder_name: self.good_results[self.FOLDER_NAME] = True elif test_name == self.file_name: self.good_results[self.FILE_NAME] = True else: logger.log(u"Nothing was good, found " + repr(test_name) + " and wanted either " + repr( self.nzb_name) + ", " + repr(self.folder_name) + ", or " + repr(self.file_name)) else: logger.log(u"Parse result not sufficient(all following have to be set). Will not save release name", logger.DEBUG) logger.log("Parse result(series_name): " + str(parse_result.series_name), logger.DEBUG) logger.log("Parse result(season_number): " + str(parse_result.season_number), logger.DEBUG) logger.log("Parse result(episode_numbers): " + str(parse_result.episode_numbers), logger.DEBUG) logger.log("Parse result(release_group): " + str(parse_result.release_group), logger.DEBUG) # for each possible interpretation of that scene name for cur_name in name_list: self._log(u"Checking scene exceptions for a match on " + cur_name, logger.DEBUG) scene_id = scene_exceptions.get_scene_exception_by_name(cur_name) if scene_id: self._log(u"Scene exception lookup got a indexer id " + str(scene_id) + ", using that", logger.DEBUG) _finalize(parse_result) return (scene_id, season, episodes) # see if we can find the name directly in the DB, if so use it for cur_name in name_list: self._log(u"Looking up " + cur_name + u" in the DB", logger.DEBUG) db_result = helpers.searchDBForShow(cur_name) if db_result: self._log(u"Lookup successful, using " + sickbeard.indexerApi(db_result[0]).name + " id " + str( db_result[1]), logger.DEBUG) _finalize(parse_result) return (int(db_result[1]), season, episodes) # see if we can find the name on the Indexer for cur_name in name_list: foundInfo = helpers.searchIndexerForShowID(cur_name, self.indexer) if foundInfo: indexer_id = foundInfo[1] self._log( u"Lookup successful, using " + sickbeard.indexerApi(self.indexer).name + " id " + str(indexer_id), logger.DEBUG) _finalize(parse_result) return (indexer_id, season, episodes) _finalize(parse_result) return to_return
def _addCacheEntry(self, name, url, season=None, episodes=None, indexer_id=0, quality=None, extraNames=[]): myDB = self._getDB() parse_result = None # if we don't have complete info then parse the filename to get it for curName in [name] + extraNames: try: myParser = NameParser() parse_result = myParser.parse(curName) except InvalidNameException: logger.log(u"Unable to parse the filename " + curName + " into a valid episode", logger.DEBUG) continue if not parse_result: logger.log(u"Giving up because I'm unable to parse this name: " + name, logger.DEBUG) return None if not parse_result.series_name: logger.log(u"No series name retrieved from " + name + ", unable to cache it", logger.DEBUG) return None indexer_lang = None if indexer_id: # if we have only the indexer_id, use the database showObj = helpers.findCertainShow(sickbeard.showList, indexer_id) if showObj: self.indexer = int(showObj.indexer) indexer_lang = showObj.lang else: logger.log(u"We were given a Indexer ID " + str(indexer_id) + " but it doesn't match a show we have in our list, so leaving indexer_id empty",logger.DEBUG) indexer_id = 0 # if no indexerID then fill out as much info as possible by searching the show name if not indexer_id: from_cache = False # check the name cache and see if we already know what show this is logger.log( u"Checking the cache for Indexer ID of " + parse_result.series_name, logger.DEBUG) # remember if the cache lookup worked or not so we know whether we should bother updating it later indexer_id = name_cache.retrieveNameFromCache(parse_result.series_name) if indexer_id: logger.log(u"Cache lookup found " + repr(indexer_id) + ", using that", logger.DEBUG) from_cache = True # if the cache failed, try looking up the show name in the database if not indexer_id: logger.log( u"Checking the database for Indexer ID of " + str(parse_result.series_name), logger.DEBUG) showResult = helpers.searchDBForShow(parse_result.series_name) if showResult: logger.log( u"" + parse_result.series_name + " was found to be show " + showResult[2] + " (" + str( showResult[1]) + ") in our DB.", logger.DEBUG) indexer_id = showResult[1] # if the database failed, try looking up the show name from scene exceptions list if not indexer_id: logger.log( u"Checking the scene exceptions list for Indexer ID of " + parse_result.series_name, logger.DEBUG) sceneResult = sickbeard.scene_exceptions.get_scene_exception_by_name(parse_result.series_name) if sceneResult: logger.log( u"" + str(parse_result.series_name) + " was found in scene exceptions list with Indexer ID: " + str(sceneResult), logger.DEBUG) indexer_id = sceneResult # if the DB lookup fails then do a comprehensive regex search if not indexer_id: logger.log( u"Checking the shows list for Indexer ID of " + str(parse_result.series_name), logger.DEBUG) for curShow in sickbeard.showList: if show_name_helpers.isGoodResult(name, curShow, False): logger.log(u"Successfully matched " + name + " to " + curShow.name + " from shows list", logger.DEBUG) indexer_id = curShow.indexerid indexer_lang = curShow.lang break # if the database failed, try looking up the show name from scene exceptions list if not indexer_id: logger.log( u"Checking Indexers for Indexer ID of " + parse_result.series_name, logger.DEBUG) # check indexers try:indexerResult = helpers.searchIndexerForShowID(parse_result.series_name) except:indexerResult = None if indexerResult: logger.log( u"" + str(parse_result.series_name) + " was found on " + str(sickbeard.indexerApi(indexerResult[0]).name) + " with Indexer ID: " + str(indexerResult[1]), logger.DEBUG) indexer_id = indexerResult[1] # if indexer_id was anything but None (0 or a number) then if not from_cache: name_cache.addNameToCache(parse_result.series_name, indexer_id) # if we came out with indexer_id = None it means we couldn't figure it out at all, just use 0 for that if indexer_id == None: indexer_id = 0 # if we found the show then retrieve the show object if indexer_id: try: showObj = helpers.findCertainShow(sickbeard.showList, indexer_id) except (MultipleShowObjectsException): showObj = None if showObj: self.indexer = int(showObj.indexer) indexer_lang = showObj.lang # if we weren't provided with season/episode information then get it from the name that we parsed if not season: season = parse_result.season_number if parse_result.season_number != None else 1 if not episodes: episodes = parse_result.episode_numbers # 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) and indexer_id: try: lINDEXER_API_PARMS = sickbeard.indexerApi(self.indexer).api_params.copy() if not (indexer_lang == "" or indexer_lang == "en" or indexer_lang == None): lINDEXER_API_PARMS['language'] = indexer_lang t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS) epObj = None if parse_result.air_by_date: epObj = t[indexer_id].airedOn(parse_result.air_date)[0] elif parse_result.sports: epObj = t[indexer_id].airedOn(parse_result.sports_date)[0] if epObj is None: return None season = int(epObj["seasonnumber"]) episodes = [int(epObj["episodenumber"])] except sickbeard.indexer_episodenotfound: logger.log(u"Unable to find episode with date " + str( parse_result.air_date) + " for show " + parse_result.series_name + ", skipping", logger.WARNING) return None except sickbeard.indexer_error, e: logger.log(u"Unable to contact " + sickbeard.indexerApi(self.indexer).name + ": " + ex(e), logger.WARNING) return None
def _addCacheEntry(self, name, url, season=None, episodes=None, indexer_id=0, quality=None, extraNames=[]): myDB = self._getDB() parse_result = None # if we don't have complete info then parse the filename to get it for curName in [name] + extraNames: try: myParser = NameParser() parse_result = myParser.parse(curName) except InvalidNameException: logger.log( u"Unable to parse the filename " + curName + " into a valid episode", logger.DEBUG) continue if not parse_result: logger.log( u"Giving up because I'm unable to parse this name: " + name, logger.DEBUG) return None if not parse_result.series_name: logger.log( u"No series name retrieved from " + name + ", unable to cache it", logger.DEBUG) return None indexer_lang = None if indexer_id: # if we have only the indexer_id, use the database showObj = helpers.findCertainShow(sickbeard.showList, indexer_id) if showObj: self.indexer = int(showObj.indexer) indexer_lang = showObj.lang else: logger.log( u"We were given a Indexer ID " + str(indexer_id) + " but it doesn't match a show we have in our list, so leaving indexer_id empty", logger.DEBUG) indexer_id = 0 # if no indexerID then fill out as much info as possible by searching the show name if not indexer_id: from_cache = False # check the name cache and see if we already know what show this is logger.log( u"Checking the cache for Indexer ID of " + parse_result.series_name, logger.DEBUG) # remember if the cache lookup worked or not so we know whether we should bother updating it later indexer_id = name_cache.retrieveNameFromCache( parse_result.series_name) if indexer_id: logger.log( u"Cache lookup found " + repr(indexer_id) + ", using that", logger.DEBUG) from_cache = True # if the cache failed, try looking up the show name in the database if not indexer_id: logger.log( u"Checking the database for Indexer ID of " + str(parse_result.series_name), logger.DEBUG) showResult = helpers.searchDBForShow(parse_result.series_name) if showResult: logger.log( u"" + parse_result.series_name + " was found to be show " + showResult[2] + " (" + str(showResult[1]) + ") in our DB.", logger.DEBUG) indexer_id = showResult[1] # if the database failed, try looking up the show name from scene exceptions list if not indexer_id: logger.log( u"Checking the scene exceptions list for Indexer ID of " + parse_result.series_name, logger.DEBUG) sceneResult = sickbeard.scene_exceptions.get_scene_exception_by_name( parse_result.series_name) if sceneResult: logger.log( u"" + str(parse_result.series_name) + " was found in scene exceptions list with Indexer ID: " + str(sceneResult), logger.DEBUG) indexer_id = sceneResult # if the DB lookup fails then do a comprehensive regex search if not indexer_id: logger.log( u"Checking the shows list for Indexer ID of " + str(parse_result.series_name), logger.DEBUG) for curShow in sickbeard.showList: if show_name_helpers.isGoodResult(name, curShow, False): logger.log( u"Successfully matched " + name + " to " + curShow.name + " from shows list", logger.DEBUG) indexer_id = curShow.indexerid indexer_lang = curShow.lang break # if the database failed, try looking up the show name from scene exceptions list if not indexer_id: logger.log( u"Checking Indexers for Indexer ID of " + parse_result.series_name, logger.DEBUG) # check indexers try: indexerResult = helpers.searchIndexerForShowID( parse_result.series_name) except: indexerResult = None if indexerResult: logger.log( u"" + str(parse_result.series_name) + " was found on " + str(sickbeard.indexerApi(indexerResult[0]).name) + " with Indexer ID: " + str(indexerResult[1]), logger.DEBUG) indexer_id = indexerResult[1] # if indexer_id was anything but None (0 or a number) then if not from_cache: name_cache.addNameToCache(parse_result.series_name, indexer_id) # if we came out with indexer_id = None it means we couldn't figure it out at all, just use 0 for that if indexer_id == None: indexer_id = 0 # if we found the show then retrieve the show object if indexer_id: try: showObj = helpers.findCertainShow(sickbeard.showList, indexer_id) except (MultipleShowObjectsException): showObj = None if showObj: self.indexer = int(showObj.indexer) indexer_lang = showObj.lang # if we weren't provided with season/episode information then get it from the name that we parsed if not season: season = parse_result.season_number if parse_result.season_number != None else 1 if not episodes: episodes = parse_result.episode_numbers # 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) and indexer_id: try: lINDEXER_API_PARMS = sickbeard.indexerApi( self.indexer).api_params.copy() if not (indexer_lang == "" or indexer_lang == "en" or indexer_lang == None): lINDEXER_API_PARMS['language'] = indexer_lang t = sickbeard.indexerApi( self.indexer).indexer(**lINDEXER_API_PARMS) epObj = None if parse_result.air_by_date: epObj = t[indexer_id].airedOn(parse_result.air_date)[0] elif parse_result.sports: epObj = t[indexer_id].airedOn(parse_result.sports_date)[0] if epObj is None: return None season = int(epObj["seasonnumber"]) episodes = [int(epObj["episodenumber"])] except sickbeard.indexer_episodenotfound: logger.log( u"Unable to find episode with date " + str(parse_result.air_date) + " for show " + parse_result.series_name + ", skipping", logger.WARNING) return None except sickbeard.indexer_error, e: logger.log( u"Unable to contact " + sickbeard.indexerApi(self.indexer).name + ": " + ex(e), logger.WARNING) return None
def massAddTable(self, rootDir=None): t = PageTemplate(rh=self, filename='home_massAddTable.mako') if not rootDir: return 'No folders selected.' elif not isinstance(rootDir, list): root_dirs = [rootDir] else: root_dirs = rootDir root_dirs = [unquote_plus(x) for x in root_dirs] if sickbeard.ROOT_DIRS: default_index = int(sickbeard.ROOT_DIRS.split('|')[0]) else: default_index = 0 if len(root_dirs) > default_index: tmp = root_dirs[default_index] if tmp in root_dirs: root_dirs.remove(tmp) root_dirs = [tmp] + root_dirs dir_list = [] main_db_con = db.DBConnection() for root_dir in root_dirs: try: file_list = ek(os.listdir, root_dir) except Exception: continue for cur_file in file_list: try: cur_path = ek(os.path.normpath, ek(os.path.join, root_dir, cur_file)) if not ek(os.path.isdir, cur_path): continue except Exception: continue cur_dir = { 'dir': cur_path, 'display_dir': '<b>{dir}{sep}</b>{base}'.format( dir=ek(os.path.dirname, cur_path), sep=os.sep, base=ek(os.path.basename, cur_path)), } # see if the folder is in KODI already dir_results = main_db_con.select( b'SELECT indexer_id ' b'FROM tv_shows ' b'WHERE location = ? LIMIT 1', [cur_path] ) if dir_results: cur_dir['added_already'] = True else: cur_dir['added_already'] = False dir_list.append(cur_dir) indexer_id = show_name = indexer = None for cur_provider in sickbeard.metadata_provider_dict.values(): if not (indexer_id and show_name): (indexer_id, show_name, indexer) = cur_provider.retrieveShowMetadata(cur_path) # default to TVDB if indexer was not detected if show_name and not (indexer or indexer_id): (_, idxr, i) = helpers.searchIndexerForShowID(show_name, indexer, indexer_id) # set indexer and indexer_id from found info if not indexer and idxr: indexer = idxr if not indexer_id and i: indexer_id = i cur_dir['existing_info'] = (indexer_id, show_name, indexer) if indexer_id and Show.find(sickbeard.showList, indexer_id): cur_dir['added_already'] = True return t.render(dirList=dir_list)
def _analyze_name(self, name, file=True): """ Takes a name and tries to figure out a show, season, and episode from it. name: A string which we want to analyze to determine show info from (unicode) Returns a (indexer_id, season, [episodes]) tuple. The first two may be None and episodes may be [] if none were found. """ logger.log(u"Analyzing name " + repr(name)) to_return = (None, None, []) if not name: return to_return # parse the name to break it into show name, season, and episode np = NameParser(file) parse_result = np.parse(name) self._log( "Parsed " + name + " into " + str(parse_result).decode('utf-8'), logger.DEBUG) if parse_result.air_by_date: season = -1 episodes = [parse_result.air_date] else: season = parse_result.season_number episodes = parse_result.episode_numbers to_return = (None, season, episodes) # do a scene reverse-lookup to get a list of all possible names name_list = show_name_helpers.sceneToNormalShowNames( parse_result.series_name) if not name_list: return (None, season, episodes) def _finalize(parse_result): self.release_group = parse_result.release_group # remember whether it's a proper if parse_result.extra_info: self.is_proper = re.search( '(^|[\. _-])(proper|repack)([\. _-]|$)', parse_result.extra_info, re.I) != None # if the result is complete then remember that for later if parse_result.series_name and parse_result.season_number != None and parse_result.episode_numbers and parse_result.release_group: test_name = os.path.basename(name) if test_name == self.nzb_name: self.good_results[self.NZB_NAME] = True elif test_name == self.folder_name: self.good_results[self.FOLDER_NAME] = True elif test_name == self.file_name: self.good_results[self.FILE_NAME] = True else: logger.log(u"Nothing was good, found " + repr(test_name) + " and wanted either " + repr(self.nzb_name) + ", " + repr(self.folder_name) + ", or " + repr(self.file_name)) else: logger.log( u"Parse result not sufficient(all following have to be set). Will not save release name", logger.DEBUG) logger.log( "Parse result(series_name): " + str(parse_result.series_name), logger.DEBUG) logger.log( "Parse result(season_number): " + str(parse_result.season_number), logger.DEBUG) logger.log( "Parse result(episode_numbers): " + str(parse_result.episode_numbers), logger.DEBUG) logger.log( "Parse result(release_group): " + str(parse_result.release_group), logger.DEBUG) # for each possible interpretation of that scene name for cur_name in name_list: self._log(u"Checking scene exceptions for a match on " + cur_name, logger.DEBUG) scene_id = scene_exceptions.get_scene_exception_by_name(cur_name) if scene_id: self._log( u"Scene exception lookup got a Indexer ID " + str(scene_id) + ", using that", logger.DEBUG) _finalize(parse_result) return (scene_id, season, episodes) # see if we can find the name directly in the DB, if so use it for cur_name in name_list: self._log(u"Looking up " + cur_name + u" in the DB", logger.DEBUG) db_result = helpers.searchDBForShow(cur_name) if db_result: self._log( u"Lookup successful, using " + sickbeard.indexerApi(db_result[0]).name + " id " + str(db_result[1]), logger.DEBUG) _finalize(parse_result) return (int(db_result[1]), season, episodes) # see if we can find the name on the Indexer for cur_name in name_list: foundInfo = helpers.searchIndexerForShowID(cur_name, self.indexer) if foundInfo: indexer_id = foundInfo[1] self._log( u"Lookup successful, using " + sickbeard.indexerApi(self.indexer).name + " id " + str(indexer_id), logger.DEBUG) _finalize(parse_result) return (indexer_id, season, episodes) _finalize(parse_result) return to_return
def massAddTable(self, rootDir=None): t = PageTemplate(rh=self, filename="home_massAddTable.mako") if not rootDir: return _("No folders selected.") elif not isinstance(rootDir, list): root_dirs = [rootDir] else: root_dirs = rootDir root_dirs = [unquote_plus(xhtml_unescape(x)) for x in root_dirs] if sickbeard.ROOT_DIRS: default_index = int(sickbeard.ROOT_DIRS.split('|')[0]) else: default_index = 0 if len(root_dirs) > default_index: tmp = root_dirs[default_index] if tmp in root_dirs: root_dirs.remove(tmp) root_dirs.insert(0, tmp) dir_list = [] main_db_con = db.DBConnection() for root_dir in root_dirs: # noinspection PyBroadException try: file_list = ek(os.listdir, root_dir) except Exception: continue for cur_file in file_list: # noinspection PyBroadException try: cur_path = ek(os.path.normpath, ek(os.path.join, root_dir, cur_file)) if not ek(os.path.isdir, cur_path): continue # ignore Synology folders if cur_file.lower() in ['#recycle', '@eadir']: continue except Exception: continue cur_dir = { 'dir': cur_path, 'display_dir': '<b>' + ek(os.path.dirname, cur_path) + os.sep + '</b>' + ek(os.path.basename, cur_path), } # see if the folder is in KODI already dirResults = main_db_con.select( "SELECT indexer_id FROM tv_shows WHERE location = ? LIMIT 1", [cur_path]) if dirResults: cur_dir['added_already'] = True else: cur_dir['added_already'] = False dir_list.append(cur_dir) indexer_id = show_name = indexer = None for cur_provider in sickbeard.metadata_provider_dict.values(): if not (indexer_id and show_name): (indexer_id, show_name, indexer) = cur_provider.retrieveShowMetadata(cur_path) # default to TVDB if indexer was not detected if show_name and not (indexer or indexer_id): (show_name_, idxr, i) = helpers.searchIndexerForShowID( show_name, indexer, indexer_id) # set indexer and indexer_id from found info if not indexer and idxr: indexer = idxr if not indexer_id and i: indexer_id = i cur_dir['existing_info'] = (indexer_id, show_name, indexer) if indexer_id and Show.find(sickbeard.showList, indexer_id): cur_dir['added_already'] = True return t.render(dirList=dir_list)