def Scan(path, files, mediaList, subdirs, language=None, root=None): # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) for idx, file in enumerate(files): log('Scan', 'file: %s', file) absFilePath = os.path.abspath(unicodize(file)) log('Scan', 'absolute file path: %s', absFilePath) # Iterate over the list of parsers and parse the file path for parser in SERIES_PARSERS: if parser.containsMatch(absFilePath) is True: log('Scan', 'parser %s contains match - parsing file path', parser) parser.parse(absFilePath, lang) showTitle = parser.getShowTitle() Log('Scan', 'show title %s', showTitle) seasonTitle = parser.getSeasonTitle() Log('Scan', 'season title %s', seasonTitle) episodeNumber = parser.getEpisodeNumber() Log('Scan', 'episode number %s', episodeNumber) episodeTitle = parser.getEpisodeTitle() Log('Scan', 'episode title %s', episodeTitle) vid = Media.Episode(showTitle, seasonTitle, episodeNumber, episodeTitle, None) if parser.getEpisodeReleaseDate() is not None: vid.released_at = parser.getEpisodeReleaseDate() vid.parts.append(file) mediaList.append(vid) print mediaList
def Scan(path, files, mediaList, subdirs, language=None, root=None): VideoFiles.Scan(path, files, mediaList, subdirs, root) for i in files: logging.debug("file:"+i) file = os.path.basename(i) logging.debug("basename:"+file) match = re.search(episode_regexp, file, re.IGNORECASE) if match: year = match.group('year') race = int(match.group('race')) sessionnumber = int(match.group('session')) session = sessionmap[sessionnumber] episode = match.group('episode') logging.debug("Found F1 episode - Year: %d, Race: %d, Session: %s, Episode: %s", year, race, session, episode) racetitle = year + " " + str(episode) + " Grand Prix" description = session + " - " + racetitle tv_show = Media.Episode(year, race, sessionnumber, description, year) tv_show.parts.append(i) mediaList.append(tv_show) logging.debug("tv_show created") Stack.Scan(path, files, mediaList, subdirs)
def Scan(path, files, mediaList, subdirs): # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs) # Take top two as show/season, but require at least the top one. paths = Utils.SplitPath(path) if len(paths) > 0 and len(paths[0]) > 0: done = False if done == False: (title, year) = VideoFiles.CleanName(paths[0]) for i in files: done = False is_movie = False file = os.path.basename(i) (file, ext) = os.path.splitext(file) # See if there's a pytivo metadata file to peek at meta = dict() metadata_filename = '{0}.txt'.format(i.replace('_LQ', '')) if os.path.isfile(metadata_filename): with open(metadata_filename, 'r') as f: for line in f: line = line.strip() if line and len(line): line_a = line.split(' : ') if len(line_a) > 1: key, value = line.split(' : ') meta[key] = value #print "pytivo metadata, ", meta # Skip tv shows based on pytivo metadata file and backup to filename if not present if 'isEpisode' in meta: if meta['isEpisode'] == 'false': is_movie = True elif file.strip().startswith('(Rec'): is_movie = True # If we still think it is not a movie then skip it if is_movie == False: print "File {0} is determined to be a tv show by pytivo metadata file, skipping".format(file) continue if 'title' in meta: title = meta['title'] if 'movieYear' in meta: year = meta['movieYear'] # Create the movie movie = Media.Movie(title, year) movie.source = VideoFiles.RetrieveSource(i) movie.parts.append(i) mediaList.append(movie)
def Scan(path, files, mediaList, subdirs, language=None, root=None): # Just look for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) # Add them all. for path in files: (show, year) = VideoFiles.CleanName(os.path.basename(path)) file = Utils.SplitPath(path)[-1] ext = file.split('.')[-1] name = '.'.join(file.split('.')[0:-1]) nameChunks = name.split(' - ') for i, chunk in enumerate(nameChunks): if parseEpisode(chunk): nameChunks = [ ' - '.join(nameChunks[:i]), nameChunks[i], ' - '.join(nameChunks[i + 1:]) ] break # correct for "-" in show name or title if len(nameChunks) > 4: if parseEpisode(nameChunks[1]) == None: if len(nameChunks[1]) >= 4: if parseEpisode(nameChunks[2]) <> None: extra = nameChunks.pop(1) nameChunks[0] = "%s - %s" % (nameChunks[0], extra) else: while len(nameChunks) > 4: extra = nameChunks.pop(3) nameChunks[2] = "%s - %s" % (nameChunks[2], extra) try: sep = parseEpisode(nameChunks[1]) if sep <> None: if len(sep) == 1: anime_ep = Media.Episode(cleanTitle(nameChunks[0]), sep[0][0], sep[0][1], nameChunks[2]) anime_ep.source = findGroup(nameChunks[2]) anime_ep.parts.append(path) mediaList.append(anime_ep) else: for ep in sep: beginEp = sep[0][1] endEp = sep[-1][1] anime_ep = Media.Episode(cleanTitle(nameChunks[0]), ep[0], ep[1], nameChunks[2]) anime_ep.source = findGroup(nameChunks[2]) anime_ep.display_offset = (ep[1] - beginEp) * 100 / ( endEp - beginEp + 1) anime_ep.parts.append(path) mediaList.append(anime_ep) except: with open('/tmp/adb-unmatchables.log', 'a') as log: log.write("%s\n" % file)
def Scan(path, files, mediaList, subdirs, language=None, root=None): try: Log.debug('path: %s', path) Log.debug('files: %s', files) Log.debug('mediaList: %s', mediaList) Log.debug('subdirs: %s', subdirs) Log.debug('language: %s', language) Log.info('root: %s', root) # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) for idx, file in enumerate(files): Log.info('file: %s', file) # http://127.0.0.1:8111/api/ep/getbyfilename?apikey=d422dfd2-bdc3-4219-b3bb-08b85aa65579&filename=%5Bjoseole99%5D%20Clannad%20-%2001%20(1280x720%20Blu-ray%20H264)%20%5B8E128DF5%5D.mkv episode_data = HttpReq("api/ep/getbyfilename?filename=%s" % (urllib.quote(os.path.basename(file)))) if len(episode_data) == 0: break if (try_get(episode_data, "code", 200) == 404): break series_data = HttpReq("api/serie/fromep?id=%d&nocast=1¬ag=1" % episode_data['id']) if (series_data["ismovie"] == 1): break # Ignore movies in preference for Shoko Movie Scanner showTitle = series_data['name'].encode( "utf-8") #no idea why I need to do this. Log.info('show title: %s', showTitle) seasonNumber = 0 seasonStr = try_get(episode_data, 'season', None) if seasonStr == None: if episode_data['eptype'] == 'Episode': seasonNumber = 1 if episode_data['eptype'] == 'Credits': seasonNumber = -1 #season -1 for OP/ED else: seasonNumber = seasonStr.split('x')[0] if seasonNumber <= 0 and Prefs['IncludeOther'] == False: break #Ignore this by choice. Log.info('season number: %s', seasonNumber) episodeNumber = int(episode_data['epnumber']) Log.info('episode number: %s', episodeNumber) vid = Media.Episode(showTitle, int(seasonNumber), episodeNumber) Log.info('vid: %s', vid) vid.parts.append(file) mediaList.append(vid) Log.info('stack media') Stack.Scan(path, files, mediaList, subdirs) Log.debug('media list %s', mediaList) except Exception as e: Log.error("Error in Scan: '%s'" % e)
def Scan(path, files, mediaList, subdirs, language=None, root=None): log('Scan', 'path: %s', path) log('Scan', 'files: %s', files) log('Scan', 'mediaList: %s', mediaList) log('Scan', 'subdirs: %s', subdirs) log('Scan', 'language: %s', language) log('Scan', 'root: %s', root) # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) for idx, file in enumerate(files): log('Scan', 'file: %s', file) # http://127.0.0.1:8111/api/ep/getbyfilename?apikey=d422dfd2-bdc3-4219-b3bb-08b85aa65579&filename=%5Bjoseole99%5D%20Clannad%20-%2001%20(1280x720%20Blu-ray%20H264)%20%5B8E128DF5%5D.mkv episode_data = HttpReq("api/ep/getbyfilename?filename=%s" % (urllib.quote(os.path.basename(file)))) if len(episode_data) == 0: break if (try_get(episode_data, "code", 200) == 404): break series_data = HttpReq("api/serie/fromep?id=%d&nocast=1¬ag=1" % episode_data['id']) showTitle = series_data['name'].encode( "utf-8") #no idea why I need to do this. log('Scan', 'show title: %s', showTitle) seasonYear = episode_data['year'] log('Scan', 'season year: %s', seasonYear) seasonNumber = 0 seasonStr = try_get(episode_data, 'season', None) if episode_data['eptype'] == 'Credits': seasonNumber = -1 #season -1 for OP/ED elif episode_data['eptype'] == 'Trailer': seasonNumber = -2 #season -2 for Trailer elif seasonStr == None: if episode_data['eptype'] == 'Episode': seasonNumber = 1 elif episode_data['eptype'] == 'Special': seasonNumber = 0 else: seasonNumber = int(seasonStr.split('x')[0]) if seasonNumber <= 0 and episode_data['eptype'] == 'Episode': seasonNumber = 1 if seasonNumber <= 0 and Prefs['IncludeOther'] == False: continue #Ignore this by choice. if (series_data["ismovie"] == 0 or seasonNumber <= 0): continue vid = Media.Movie(showTitle, int(seasonYear)) log('Scan', 'vid: %s', vid) vid.parts.append(file) mediaList.append(vid) log('Scan', 'stack media') Stack.Scan(path, files, mediaList, subdirs) log('Scan', 'media list %s', mediaList)
def Scan(path, files, mediaList, subdirs, language=None, root=None): # Just look for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) # Add them all. for i in files: name, year = VideoFiles.CleanName(os.path.basename(i)) movie = Media.Movie(name, year) movie.parts.append(i) mediaList.append(movie)
def Scan(path, files, mediaList, subdirs, language=None, root=None): VideoFiles.Scan(path, files, mediaList, subdirs, root) # require alphabetic order files.sort() # group movie parts as they come in sequence prev_media = None prev_part_index = None for file in files: attr = xattr_metadata(file) if attr is None: continue guid = movie_guid(attr) if guid is None: continue print("[XATTR] %s | %s" % (guid, attr)) part_index = movie_part_index(attr) if prev_part_index and part_index and prev_part_index + 1 == part_index and prev_media.guid == guid: prev_part_index = part_index prev_media.parts.append(file) print("[MEDIA] %s | Part %s" % (prev_media, part_index)) continue media = Media.Movie( movie_name(attr).encode( 'utf-8'), # use str since Plex doesn't like unicode strings movie_year(attr)) media.guid = guid.encode('utf-8') original_filename = xattr_filename(file) if original_filename: media.source = VideoFiles.RetrieveSource( original_filename.encode('utf-8')) media.parts.append(file) mediaList.append(media) if part_index == 1: prev_media = media prev_part_index = 1 else: prev_media = None prev_part_index = None print("[MEDIA] %s | %s | %s | %s" % (media, media.year, media.released_at, media.source))
def Scan(path, files, mediaList, subdirs, language=None, root=None): VideoFiles.Scan(path, files, mediaList, subdirs, root) for file in files: attr = xattr_metadata(file) if attr is None: continue print("[XATTR] %s" % attr) # single episode | multi episode episodes = list_episodes(attr) multi_episode_count = len(episodes) for i, attr in enumerate(episodes): guid = series_guid(attr) name = series_name(attr) special = episode_special_number(attr) media = Media.Episode( name.encode( 'utf-8' ), # use str since Plex doesn't like unicode strings 0 if special else episode_season_number(attr), special if special else episode_number(attr), episode_title(attr).encode( 'utf-8' ), # use str since Plex doesn't like unicode strings series_year(attr)) date = episode_date(attr) if date: media.released_at = date.strftime('%Y-%m-%d') if (multi_episode_count > 1): media.display_offset = (i * 100) / multi_episode_count original_filename = xattr_filename(file) if original_filename: media.source = VideoFiles.RetrieveSource( original_filename.encode('utf-8')) media.parts.append(file) mediaList.append(media) print("[MEDIA] %s | %s | %s | %s" % (media, media.year, media.released_at, media.source))
def Scan(path, files, mediaList, subdirs, lang=None, root=None): log('Scan', '') log('Scan', 'path: %s', path) log('Scan', 'files: %s', files) log('Scan', 'mediaList: %s', mediaList) log('Scan', 'subdirs: %s', subdirs) log('Scan', 'lang: %s', lang) log('Scan', 'root: %s', root) # For each directory Scan is called for, the directories' files ( that is not sub directories ) are passed in as well. # The VideoFiles automatically filters for filetypes that are typically not wanted. Removing .txt etc VideoFiles.Scan(path, files, mediaList, subdirs, root) ## Files Array will now be populated with 'desireable' files. These are strings of the full file and path for idx, file in enumerate(files): log('Scan:VideoFiles', 'VideoFiles: %s', file)
def Scan(path, files, mediaList, subdirs, language=None, root=None): # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) # Take top two as show/season, but require at least the top one. paths = Utils.SplitPath(path) shouldStack = True if len(paths) == 1 and len(paths[0]) == 0: # Run the select regexps we allow at the top level. for i in files: try: file = os.path.basename(i) for rx in episode_regexps[0:-1]: match = re.search(rx, file, re.IGNORECASE) if match: # Extract data. show = match.group('show') if match.groupdict( ).has_key('show') else '' season = match.group('season') if season.lower() == 'sp': season = 0 episode = int(match.group('ep')) endEpisode = episode if match.groupdict().has_key( 'secondEp') and match.group('secondEp'): endEpisode = int(match.group('secondEp')) # Clean title. name, year = VideoFiles.CleanName(show) if len(name) > 0: for ep in range(episode, endEpisode + 1): tv_show = Media.Episode( name, season, ep, '', year) tv_show.display_offset = ( ep - episode) * 100 / (endEpisode - episode + 1) tv_show.parts.append(i) mediaList.append(tv_show) except Exception, e: pass
def Scan(path, files, mediaList, subdirs): # Scan for video files. print files VideoFiles.Scan(path, files, mediaList, subdirs) scanner = GenericScanner() # Run the select regexps we allow at the top level. for file in files: filename, ext = os.path.splitext(os.path.basename(file)) show = customScan(filename) if show is None: show = scanner.scan(filename) if show is None: show = scanner.scan(file) if show is not None: print(filename) print( " Show: %s\n Season: %d\n episode: %d\n title: %s\n Year: %s" % (show.show, show.season, show.episode, show.name, show.year)) show.parts.append(file) mediaList.append(show)
def Scan(path, files, mediaList, subdirs, language=None, root=None): filesToRemove = [] # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) # Take top two as show/season, but require at least the top one. paths = Utils.SplitPath(path) if len(paths) == 1 and len(paths[0]) == 0: # Run the select regexps we allow at the top level. for i in files: file = os.path.basename(i) match = re.search(regexp, file, re.IGNORECASE) if match: # Extract data. show = match.group('show') year = int(match.group('year')) month = int(match.group('month')) day = int(match.group('day')) # Clean title. name, _ = VideoFiles.CleanName(show) if len(name) > 0: # Use the year as the season. tv_show = Media.Episode(name, year, None, None, None) tv_show.released_at = '%d-%02d-%02d' % (year, month, day) tv_show.parts.append(i) mediaList.append(tv_show) filesToRemove.append(i) # Uniquify and remove. for i in list(set(filesToRemove)): files.remove(i) SeriesScanner.Scan(path, files, mediaList, subdirs, language, root)
def Scan(path, files, mediaList, subdirs): VideoFiles.Scan(path, files, mediaList, subdirs) paths = Utils.SplitPath(path) logging.debug("---------------------------------------------------") logging.debug("Paths: %s" % paths) if len(paths) == 1 and len(paths[0]) > 0: pathAnime = paths[0] (animeName, animeYear) = getAnime(pathAnime) findEpisodes(animeName, animeYear, 1, files, mediaList) elif len(paths) == 2: pathAnime = paths[0] (animeName, animeYear) = getAnime(pathAnime) pathSeason = paths[1] seasonNumber = getSeason(pathSeason) findEpisodes(animeName, animeYear, seasonNumber, files, mediaList) Stack.Scan(path, files, mediaList, subdirs)
def Scan(path, files, mediaList, subdirs): print "********************************************" print "Starting scan of " + path # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs) print "After videofiles scan " + path # Run the select regexps we allow at the top level. for i in files: file = os.path.basename(i) print "File found: " + file for rx in episode_regexps[0:1]: match = re.search(rx, file, re.IGNORECASE) if match: # Extract data. print "Match found on file: " + file show = match.group('show') year = int(match.group('year')) month = int(match.group('month')) day = int(match.group('day')) ep = '%0*d' % (2, month) + '%0*d' % (2, day) title = '%0*d' % (4, year) + "-" + ep print "Extracted Details:" print "Show: " + show print "Year: " + '%0*d' % (4, year) print "Month: " + '%0*d' % (2, month) print "Day:" + '%0*d' % (2, day) print "ep: " + ep print "Title: " + title if len(show) > 0: tv_show = Media.Episode(show, year, ep, ep, None) tv_show.released_at = '%d-%02d-%02d' % (year, month, day) tv_show.parts.append(i) mediaList.append(tv_show) else: print 'No match found on %s' % file # Stack the results. Stack.Scan(path, files, mediaList, subdirs)
def Scan(path, files, mediaList, subdirs): # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs) LogMsg("SicktubeScanner.VideoFiles.Scan({0}, {1}, {2}, {3})".format( path, files, mediaList, subdirs)) for mediaFile in files: (file, ext) = os.path.splitext(mediaFile) if ext == 'json': continue infoJsonFile = file + '.info.json' LogMsg("{0} | {1} | {2} | {3}".format(os.path.basename(mediaFile), mediaFile, infoJsonFile, os.path.exists(infoJsonFile))) # Create the movie (name, ext) = os.path.splitext(os.path.basename(mediaFile)) # Is there a .info.json file indicating we've used our scanner? if not os.path.exists(infoJsonFile): movie = Media.Movie(name) movie.parts.append(mediaFile) else: downloadInfo = json.load(open(infoJsonFile)) movie = Media.Movie("{0}".format(downloadInfo['title'])) #movie = Media.Movie(os.path.basename(mediaFile)) movie.parts.append(mediaFile) # Source URL if 'webpage_url' in downloadInfo: movie.source = "{0}".format(downloadInfo['webpage_url']) # Website/Movie ID if 'id' in downloadInfo: movie.guid = "{0}".format(downloadInfo['id']) # Year if 'upload_date' in downloadInfo: dateObj = datetime.strptime(downloadInfo['upload_date'], '%Y%m%d') movie.year = "{0}".format(dateObj.year) mediaList.append(movie) # Stack the results. Stack.Scan(path, files, mediaList, subdirs)
def Scan(path, files, mediaList, subdirs, language=None, root=None): log('Scan', 'path: %s', path) log('Scan', 'files: %s', files) log('Scan', 'mediaList: %s', mediaList) log('Scan', 'subdirs: %s', subdirs) log('Scan', 'language: %s', language) log('Scan', 'root: %s', root) # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) for idx, file in enumerate(files): log('Scan', 'file: %s', file) # http://127.0.0.1:8111/api/ep/getbyfilename?apikey=d422dfd2-bdc3-4219-b3bb-08b85aa65579&filename=%5Bjoseole99%5D%20Clannad%20-%2001%20(1280x720%20Blu-ray%20H264)%20%5B8E128DF5%5D.mkv episode_data = HttpReq("api/ep/getbyfilename?filename=%s" % (urllib.quote(os.path.basename(file)))) if len(episode_data) == 0: break if (try_get(episode_data, "code", 200) == 404): break series_data = HttpReq("api/serie/fromep?id=%d&nocast=1¬ag=1" % episode_data['id']) if (series_data["ismovie"] == 0): continue showTitle = series_data['name'].encode( "utf-8") #no idea why I need to do this. log('Scan', 'show title: %s', showTitle) seasonYear = episode_data['year'] log('Scan', 'season year: %s', seasonYear) vid = Media.Movie(showTitle, int(seasonYear)) log('Scan', 'vid: %s', vid) vid.parts.append(file) mediaList.append(vid) log('Scan', 'stack media') Stack.Scan(path, files, mediaList, subdirs) log('Scan', 'media list %s', mediaList)
def Scan(path, files, mediaList, subdirs, language=None, root=None): # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) filesToRemove = [] for i in files: file = os.path.basename(i).lower() if re.match(episode_regexp, file): filesToRemove.append(i) else: for j in VideoFiles.source_dict['dtv']: if j in file: filesToRemove.append(i) break # Uniquify and remove. for i in list(set(filesToRemove)): files.remove(i) MovieScanner.Scan(path, files, mediaList, subdirs, language, root)
def Scan(path, files, mediaList, subdirs, language=None, root=None): Log.debug('path: %s', path) Log.debug('files: %s', files) Log.debug('subdirs: %s', subdirs) # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) for idx, file in enumerate(files): try: Log.info('file: %s', file) # http://127.0.0.1:8111/api/ep/getbyfilename?apikey=d422dfd2-bdc3-4219-b3bb-08b85aa65579&filename=%5Bjoseole99%5D%20Clannad%20-%2001%20(1280x720%20Blu-ray%20H264)%20%5B8E128DF5%5D.mkv episode_data = HttpReq("api/ep/getbyfilename?filename=%s" % (urllib.quote(os.path.basename(file)))) if len(episode_data) == 0: continue if (try_get(episode_data, "code", 200) == 404): continue series_data = HttpReq("api/serie/fromep?id=%d&nocast=1¬ag=1" % episode_data['id']) if not (try_get(series_data, "ismovie", 0)) or (episode_data['eptype'] != 'Episode'): continue # Skip series and extras showTitle = series_data['name'].encode("utf-8") #no idea why I need to do this. Log.info('show title: %s', showTitle) seasonYear = episode_data['year'] Log.info('season year: %s', seasonYear) vid = Media.Movie(showTitle, int(seasonYear)) Log.info('vid: %s', vid) vid.parts.append(file) mediaList.append(vid) except Exception as e: Log.error("Error in Scan: '%s'" % e) continue Log.info('Scan', 'stack media') Stack.Scan(path, files, mediaList, subdirs) Log.info('Scan', 'media list %s', mediaList)
def Scan(path, files, mediaList, subdirs, lang=None, root=None): log('Scan', '') log('Scan', 'path: %s', path) log('Scan', 'files: %s', files) log('Scan', 'mediaList: %s', mediaList) log('Scan', 'subdirs: %s', subdirs) log('Scan', 'lang: %s', lang) log('Scan', 'root: %s', root) # For each directory Scan is called for, the directories' files ( that is not sub directories ) are passed in as well. # The VideoFiles automatically filters for filetypes that are typically not wanted. Removing .txt etc VideoFiles.Scan(path, files, mediaList, subdirs, root) ## Files Array will now be populated with 'desireable' files. These are strings of the full file and path for idx, file in enumerate(files): log('Scan:VideoFiles', 'VideoFiles: %s', file) # Lang, appears to be the Library Path of the file, and we want to remove that to get the important parts file_path = file.replace(lang, '') log('Scan:ForEachFile', 'Important bits: %s', file_path) # Using the File Delimiter, split the string split_path = file_path.split('/') log('Scan:ForEachFile', 'Split bits: %s', split_path) # For the Lazy if three , Else if four if len(split_path) == 3: media = Media.Episode(split_path[1], None, None, split_path[2], None) if len(split_path) == 4: media = Media.Episode(split_path[1], split_path[2], None, split_path[3], None) media.parts.append(file) mediaList.append(media) print mediaList
def Scan(path, files, mediaList, subdirs, language=None, root=None): VideoFiles.Scan(path, files, mediaList, subdirs, root) paths = Utils.SplitPath(path) shouldStack = True logger.debug('=====================================================') logger.debug('- path:%s' % path) logger.debug('- files count:%s' % len(files)) logger.debug('- subdir count:%s' % len(subdirs)) for _ in subdirs: logger.debug(' * %s' % _) if len(paths) != 0: logger.debug('- paths[0] : %s' % paths[0]) logger.debug('- files count : %s', len(files)) for i in files: tempDone = False try: file = os.path.basename(i) logger.debug(' * FILE : %s' % file) #for idx, rx in enumerate(episode_regexps): for rx in episode_regexps: match = re.search(rx, file, re.IGNORECASE) if match: show = match.group('show').replace( '.', '') if match.groupdict().has_key('show') else '' season = 1 episode = int(match.group('ep')) name, year = VideoFiles.CleanName(show) name = re.sub(r'((.*?기획)|(미니시리즈)|(.*?드라마)|(.*?특집))', '', name).strip() logger.debug( ' - MATCH show:[%s] name:[%s] episode:[%s] year:[%s]', show, name, episode, year) if len(name) > 0: tv_show = Media.Episode(name, season, episode, '', year) tv_show.display_offset = 0 tv_show.parts.append(i) mediaList.append(tv_show) logger.debug(' - APPEND by episode: %s' % tv_show) tempDone = True break if tempDone == False: for rx in date_regexps: match = re.search(rx, file) if match: year = int(match.group('year')) + 2000 month = int(match.group('month')) day = int(match.group('day')) show = match.group('show') tv_show = Media.Episode(show, year, None, None, None) tv_show.released_at = '%d-%02d-%02d' % (year, month, day) tv_show.parts.append(i) mediaList.append(tv_show) logger.debug(' - APPEND by date: %s' % tv_show) tempDone = True break if tempDone == False: logger.error(' NOT APPEND!!') except Exception, e: logger.error(e)
def Scan(path, files, mediaList, subdirs, language=None, root=None, **kwargs): # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) # Check for DVD rips. paths = Utils.SplitPath(path) video_ts = Utils.ContainsFile(files, 'video_ts.ifo') if video_ts is None: video_ts = Utils.ContainsFile(files, 'video_ts.bup') if len(paths) >= 1 and len(paths[0]) > 0 and video_ts is not None: print "Found a DVD" name = year = None # Now find the name. if paths[-1].lower() == 'video_ts' and len(paths) >= 2: # Easiest case. (name, year) = VideoFiles.CleanName(paths[-2]) else: # Work up until we find a viable candidate. backwardsPaths = paths backwardsPaths.reverse() for p in backwardsPaths: if re.match(nice_match, p): (name, year) = VideoFiles.CleanName(p) break if name is None: # Use the topmost path. (name, year) = VideoFiles.CleanName(paths[0]) movie = Media.Movie(name, year) # Add the video_ts file first. movie.parts.append(video_ts) biggestFile = None biggestSize = 0 for i in files: if os.path.splitext(i)[1].lower( ) == '.vob' and os.path.getsize(i) > biggestSize: biggestSize = os.path.getsize(i) biggestFile = i # Add the biggest part so that we can get thumbnail/art/analysis from it. if biggestFile is not None: movie.parts.append(biggestFile) if len(movie.parts) > 0: movie.guid = checkNfoFile(movie.parts[0], 1) mediaList.append(movie) # Check for Bluray rips. elif len(paths) >= 3 and paths[-1].lower() == 'stream' and paths[-2].lower( ) == 'bdmv': (name, year) = VideoFiles.CleanName(paths[-3]) movie = Media.Movie(name, year) for i in files: movie.parts.append(i) mediaList.append(movie) else: # Make movies! for i in files: file = os.path.basename(i) (name, year) = VideoFiles.CleanName(os.path.splitext(file)[0]) # If it matches a TV show, don't scan it as a movie. tv = False for rx in SeriesScanner.episode_regexps[0:-1]: if re.match(rx, file): print "The file", file, "looked like a TV show so we're skipping it (", rx, ")" tv = True if tv == False: # OK, it's a movie movie = Media.Movie(name, year) movie.source = VideoFiles.RetrieveSource(file) movie.parts.append(i) mediaList.append(movie) # Stack the results. Stack.Scan(path, files, mediaList, subdirs) # Clean the folder name and try a match on the folder. if len(path) > 0: folderName = os.path.basename(path).replace(' ', ' ').replace(' ', '.') (cleanName, year) = VideoFiles.CleanName(folderName) if len(mediaList) == 1 and re.match(nice_match, cleanName): res = re.findall(nice_match, cleanName) mediaList[0].name = res[0][0] mediaList[0].year = res[0][1] elif len(mediaList) == 1 and (len(cleanName) > 1 or year is not None): mediaList[0].name = cleanName mediaList[0].year = year # Check for a folder with multiple 'CD' subfolders and massage foundCDsubdirs = {} for s in subdirs: m = re.match('cd[ ]*([0-9]+)', os.path.basename(s).lower()) if m: foundCDsubdirs[int(m.groups(1)[0])] = s # More than one cd subdir, let's stack and whack subdirs. if len(foundCDsubdirs) > 1: name, year = VideoFiles.CleanName(os.path.basename(path)) movie = Media.Movie(name, year) movie.guid = checkNfoFile( os.path.dirname(foundCDsubdirs.values()[0]), 1) keys = foundCDsubdirs.keys() keys.sort() for key in keys: d = foundCDsubdirs[key] subFiles = [] for f in os.listdir(d): subFiles.append(os.path.join(d, f)) VideoFiles.Scan(d, subFiles, mediaList, [], None) subdirs.remove(d) movie.parts += subFiles if len(movie.parts) > 0: mediaList.append(movie) # See if we can find a GUID. for mediaItem in mediaList: if mediaItem.guid is None: mediaItem.guid = checkNfoFile(mediaItem.parts[0], len(mediaList)) if len(mediaList) == 1: if mediaList[0].source is None: mediaList[0].source = VideoFiles.RetrieveSource(path) # If the subdirectories indicate that we're inside a DVD, when whack things other than audio and video. whack = [] if 'video_ts' in [Utils.SplitPath(s)[-1].lower() for s in subdirs]: for dir in subdirs: d = os.path.basename(dir).lower() if d not in ['video_ts', 'audio_ts']: whack.append(dir) # Finally, if any of the subdirectories match a TV show, don't enter! for dir in subdirs: for rx in standalone_tv_regexs: res = re.findall(rx, dir) if len(res): whack.append(dir) for w in whack: subdirs.remove(w)
def Scan(path, files, mediaList, subdirs, language=None, root=None): # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) # Take top two as show/season, but require at least the top one. paths = Utils.SplitPath(path) if len(paths) == 1 and len(paths[0]) == 0: # Run the select regexps we allow at the top level. for i in files: file = os.path.basename(i) for rx in episode_regexps[0:-1]: match = re.search(rx, file, re.IGNORECASE) if match: # Extract data. show = match.group('show') season = int(match.group('season')) episode = int(match.group('ep')) endEpisode = episode if match.groupdict().has_key('secondEp') and match.group( 'secondEp'): endEpisode = int(match.group('secondEp')) # Clean title. name, year = VideoFiles.CleanName(show) if len(name) > 0: for ep in range(episode, endEpisode + 1): tv_show = Media.Episode(name, season, ep, '', year) tv_show.display_offset = (ep - episode) * 100 / ( endEpisode - episode + 1) tv_show.parts.append(i) mediaList.append(tv_show) elif len(paths) > 0 and len(paths[0]) > 0: done = False # See if parent directory is a perfect match (e.g. a directory like "24 - 8x02 - Day 8_ 5_00P.M. - 6_00P.M") if len(files) == 1: for rx in standalone_episode_regexs: res = re.findall(rx, paths[-1]) if len(res): show, junk, year, season, episode, junk, endEpisode, junk, title = res[ 0] # If it didn't have a show, then grab it from the directory. if len(show) == 0: (show, year) = VideoFiles.CleanName(paths[0]) episode = int(episode) if len(endEpisode) > 0: endEpisode = int(endEpisode) else: endEpisode = episode for ep in range(episode, endEpisode + 1): tv_show = Media.Episode(show, season, ep, title, year) tv_show.display_offset = (ep - episode) * 100 / ( endEpisode - episode + 1) tv_show.parts.append(files[0]) mediaList.append(tv_show) done = True break if done == False: # Not a perfect standalone match, so get information from directories. (e.g. "Lost/Season 1/s0101.mkv") season = None seasonNumber = None (show, year) = VideoFiles.CleanName(paths[0]) # Which component looks like season? if len(paths) >= 2: season = paths[len(paths) - 1] match = re.match(season_regex, season, re.IGNORECASE) if match: seasonNumber = int(match.group('season')) # Make sure an episode name didn't make it into the show. for rx in ends_with_episode: show = re.sub(rx, '', show) for i in files: done = False file = os.path.basename(i) (file, ext) = os.path.splitext(file) if ext.lower() in ['.mp4', '.m4v', '.mov']: m4season = m4ep = m4year = 0 m4show = title = '' try: mp4fileTags = mp4file.Mp4File(i) # Show. try: m4show = find_data( mp4fileTags, 'moov/udta/meta/ilst/tvshow').encode('utf-8') except: pass # Season. try: m4season = int( find_data(mp4fileTags, 'moov/udta/meta/ilst/tvseason')) except: pass # Episode. m4ep = None try: # tracknum (can be 101) m4ep = int( find_data(mp4fileTags, 'moov/udta/meta/ilst/tracknum')) except: try: # tvepisodenum (can be S2E16) m4ep = find_data( mp4fileTags, 'moov/udta/meta/ilst/tvepisodenum') except: # TV Episode (can be 101) m4ep = int( find_data(mp4fileTags, 'moov/udta/meta/ilst/tvepisode')) if m4ep is not None: found = False try: # See if it matches regular expression. for rx in episode_regexps[:-1]: match = re.search(rx, file, re.IGNORECASE) if match: m4season = int(match.group('season')) m4ep = int(match.group('ep')) found = True if found == False and re.match( '[0-9]+', str(m4ep)): # Carefully convert to episode number. m4ep = int(m4ep) % 100 elif found == False: m4ep = int(re.findall('[0-9]+', m4ep)[0]) except: pass # Title. try: title = find_data( mp4fileTags, 'moov/udta/meta/ilst/title').encode('utf-8') except: pass # Year. try: m4year = int( find_data(mp4fileTags, 'moov/udta/meta/ilst/year')[:4]) except: pass if year and m4year == 0: m4year = year # If we have all the data we need, add it. if len(m4show) > 0 and m4season > 0 and m4ep > 0: tv_show = Media.Episode(m4show, m4season, m4ep, title, m4year) tv_show.parts.append(i) mediaList.append(tv_show) continue except: pass # Check for date-based regexps first. for rx in date_regexps: match = re.search(rx, file) if match: year = int(match.group('year')) month = int(match.group('month')) day = int(match.group('day')) # Use the year as the season. tv_show = Media.Episode(show, year, None, None, None) tv_show.released_at = '%d-%02d-%02d' % (year, month, day) tv_show.parts.append(i) mediaList.append(tv_show) done = True break if done == False: # Take the year out, because it's not going to help at this point. cleanName, cleanYear = VideoFiles.CleanName(file) if cleanYear != None: file = file.replace(str(cleanYear), 'XXXX') # Minor cleaning on the file to avoid false matches on H.264, 720p, etc. whackRx = [ '([hHx][\.]?264)[^0-9]', '[^[0-9](720[pP])', '[^[0-9](1080[pP])', '[^[0-9](480[pP])' ] for rx in whackRx: file = re.sub(rx, ' ', file) for rx in episode_regexps: match = re.search(rx, file, re.IGNORECASE) if match: # Parse season and episode. the_season = int(match.group('season')) episode = int(match.group('ep')) endEpisode = episode if match.groupdict().has_key( 'secondEp') and match.group('secondEp'): endEpisode = int(match.group('secondEp')) # More validation for the weakest regular expression. if rx == episode_regexps[-1]: # Look like a movie? Skip it. if re.match('.+ \([1-2][0-9]{3}\)', paths[-1]): done = True break # Skip episode 0 on the weak regex since it's pretty much never right. if the_season == 0: break # Make sure this isn't absolute order. if seasonNumber is not None: if seasonNumber != the_season: # Something is amiss, see if it starts with an episode numbers. if re.search('^[0-9]+[ -]', file): # Let the episode matcher have it. break # Treat the whole thing as an episode. episode = episode + the_season * 100 if endEpisode is not None: endEpisode = endEpisode + the_season * 100 for ep in range(episode, endEpisode + 1): tv_show = Media.Episode( show, the_season, ep, None, year) tv_show.display_offset = ( ep - episode) * 100 / (endEpisode - episode + 1) tv_show.parts.append(i) mediaList.append(tv_show) done = True break if done == False: # OK, next let's see if we're dealing with something that looks like an episode. # Begin by cleaning the filename to remove garbage like "h.264" that could throw # things off. # (file, fileYear) = VideoFiles.CleanName(file) # if don't have a good year from before (when checking the parent folders) AND we just got a good year, use it. if not year and fileYear: year = fileYear for rx in just_episode_regexs: episode_match = re.search(rx, file, re.IGNORECASE) if episode_match is not None: the_episode = int(episode_match.group('ep')) the_season = 1 # Now look for a season. if seasonNumber is not None: the_season = seasonNumber # See if we accidentally parsed the episode as season. if the_episode >= 100 and int( the_episode / 100) == the_season: the_episode = the_episode % 100 tv_show = Media.Episode(show, the_season, the_episode, None, year) tv_show.parts.append(i) mediaList.append(tv_show) done = True break if done == False: print "Got nothing for:", file # Stack the results. Stack.Scan(path, files, mediaList, subdirs)
def Scan(path, files, mediaList, subdirs, language=None, root=None): subdirs_to_whack = [] for subdir in subdirs: excludedBasename = os.path.basename(subdir).lower() log('Subdir', 'basename: %s', excludedBasename) if str(excludedBasename) == 'exercise files': log('Subdir to Whack', excludedBasename) subdirs_to_whack.append(subdir) if str(excludedBasename) == 'files': log('Subdir to Whack', excludedBasename) subdirs_to_whack.append(subdir) if str(excludedBasename) == 'source files': log('Subdir to Whack', excludedBasename) subdirs_to_whack.append(subdir) subdirs_to_whack = list(set(subdirs_to_whack)) for subdir in subdirs_to_whack: subdirs.remove(subdir) log('Subdir Ignored', os.path.basename(subdir).lower()) # List of series parsers series_parsers = [SeriesEpisodeMediaParser()] # Stores the configuration map config_map = ConfigMap() log('Scan', 'path: %s', path) log('Scan', 'files: %s', files) log('Scan', 'mediaList: %s', mediaList) log('Scan', 'subdirs: %s', subdirs) log('Scan', 'language: %s', language) log('Scan', 'root: %s', root) # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) for idx, file in enumerate(files): log('Scan', 'file: %s', file) absFilePath = os.path.abspath(file) absRootDir = os.path.abspath(root) log('Scan', 'absolute file path: %s', absFilePath) parsers = [] # Check the customParser map for this file customParser = config_map.findCustomParser(absRootDir, absFilePath) if customParser is not None: # If we have a custom parser use only this parser on the file parsers = [customParser] else: # We are using the default parsers parsers = series_parsers # Iterate over the list of parsers and parse the file path for parser in parsers: log('Scan', 'parser %s', parser) if parser.containsMatch(absFilePath) is True: log('Scan', 'parser %s contains match - parsing file path', parser) parser.parse(absFilePath, language) showTitle = parser.getShowTitle() log('Scan', 'show title: %s', showTitle) seasonNumber = parser.getSeasonNumber() log('Scan', 'season number: %s', seasonNumber) seasonTitle = parser.getSeasonTitle() log('Scan', 'season number: %s', seasonNumber) seasonYear = parser.getSeasonYear() log('Scan', 'season year: %s', seasonYear) episodeNumber = parser.getEpisodeNumber() log('Scan', 'episode number: %s', episodeNumber) episodeTitle = parser.getEpisodeTitle() log('Scan', 'episode title: %s', episodeTitle) vid = Media.Episode(showTitle, seasonNumber, episodeNumber, episodeTitle, seasonYear) vid.parts.append(file) mediaList.append(vid) break # stack files log('Scan', 'stack media') Stack.Scan(path, files, mediaList, subdirs) log('Scan', 'media list %s', mediaList)
def Scan(path, files, mediaList, subdirs): # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs) # Take top two as show/season, but require at least the top one. paths = Utils.SplitPath(path) if len(paths) > 0 and len(paths[0]) > 0: done = False if done == False: # Not a perfect standalone match, so get information from directories. (e.g. "Lost/Season 1/s0101.mkv") season = None seasonNumber = None (show, year) = VideoFiles.CleanName(paths[0]) for i in files: done = False file = os.path.basename(i) (file, ext) = os.path.splitext(file) # See if there's a pytivo metadata file to peek at meta = dict() metadata_filename = '{0}.txt'.format(i.replace('_LQ', '')) if os.path.isfile(metadata_filename): with open(metadata_filename, 'r') as f: for line in f: line = line.strip() if line and len(line): line_a = line.split(' : ') if len(line_a) > 1: key, value = line.split(' : ') meta[key] = value #print "pytivo metadata, ", meta # Skip tv shows based on pytivo metadata file and backup to filename if not present is_movie = False if 'isEpisode' in meta: if meta['isEpisode'] == 'false': is_movie = True elif file.strip().startswith('(Rec'): is_movie = True # Skip tivo recorded movies if is_movie == True: print "File {0} is determined to be a movie, skipping".format( file) continue # Test for matching tivo server files found = False for rx in episode_regexps: match = re.search(rx, file, re.IGNORECASE) if match: season = int(match.group('season')) if match.group( 'season') and match.group('season') != '' else None episode = int(match.group('ep')) if match.group( 'ep') and match.group('ep') != '' else None try: title = match.group('title') if match.group( 'title') else None except IndexError: title = None if 'episodeTitle' in meta: title = meta['episodeTitle'] if 'seriesTitle' in meta: show = meta['seriesTitle'] originalAirDate = None if 'originalAirDate' in meta: originalAirDate = meta['originalAirDate'].split( 'T')[0] if season is None and episode is None and title is None: continue if season is None and originalAirDate: season = int(originalAirDate.split('-')[0]) found = True tv_show = Media.Episode(show, season, episode, title, None) if originalAirDate is not None: tv_show.released_at = originalAirDate tv_show.parts.append(i) mediaList.append(tv_show) break if found == True: continue if done == False: print "Got nothing for:", file # Stack the results. Stack.Scan(path, files, mediaList, subdirs)
def Scan(path, files, mediaList, subdirs): print "SS: Starting scan" #print "SS: path |", path, "|" #print "SS: files |", files, "|" #print "SS: subdirs |", subdirs, "|" # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs) # print "SS: files |", files, "|" # print "SS: subdirs |", subdirs, "|" # Here we have only video files in files, path is only the TLD, media is empty, subdirs is populated # No files here? Then what are we doing! clean_files = dict() if len(files) == 0: return else: for i in files: file = os.path.basename(i) (file, ext) = os.path.splitext(file) # Minor cleaning on the file to avoid false matches on H.264, 720p, etc. whackRx = [ '([hHx][\.]?264)[^0-9].*', '[^[0-9](720[pP]).*', '[^[0-9](1080[pP]).*', '[^[0-9](480[pP]).*', '[^[0-9](540[pP]).*' ] for rx in whackRx: file = re.sub(rx, "", file) clean_files[file] = i paths = Utils.SplitPath(path) if len(paths) == 1 and len(paths[0]) == 0 or len(path) == 0: # This is just a load of files dumped in the root directory - we can't deal with this properly print "SS: In TLD, no files here can be scanned" return elif len(paths) == 1 and len(paths[0]) > 0: # These files have been dumped into a League directory but have no seasons. for file in clean_files: print "SS: Working on file | {0} |".format(file) for rx in regex_all_in_file_name: match = re.search(rx, file, re.IGNORECASE) if match: print "SS: matched regex | {0} |".format(rx) year = match.group('year') month = int(match.group('month')) day = int(match.group('day')) show = re.sub('[^0-9a-zA-Z]+', ' ', match.group('show')) title = re.sub('[^0-9a-zA-Z]+', ' ', match.group('title')) if 'season' in match.groups(): season = match.group('season') else: season = year # Work out where the .SportScanner file should be filename = re.sub(r'(.*\\).*?$', r'\1SportScanner.txt', clean_files[file]) print "SS: FileName: {0}".format(filename) # Check to see if a .SportScanner file exists, then read in the contents if os.path.isfile(filename): size = os.path.getsize(filename) fd = os.open(filename, os.O_RDONLY) file_contents = os.read(fd, size) # print "SS: FileContents: {0}".format(file_contents) season_match = re.search('(?P<season>XX..)', file_contents, re.IGNORECASE) if season_match: season_format = season_match.group( 'season').lower() print "SS: Using {0} season format for {1}".format( season_format, show) if season_format == "xxyy": # If this is a split season then get the dates split_dates_match = re.search( r'(?P<month>\d{1,2}),(?P<day>\d{1,2})', file_contents, re.IGNORECASE) if split_dates_match: split_month = int( split_dates_match.group('month')) split_day = int( split_dates_match.group('day')) print "SS: Split date is {0}-{1}".format( split_month, split_day) print "SS: Event date is {0}-{1}".format( month, day) if month < split_month or ( month == split_month and day < split_day): print "SS: Event happened before split date" short_year = year[-2:] year_before = str(int(short_year) - 1) season = int("{0}{1}".format( year_before, short_year)) else: print "SS: Event happened after split date" short_year = year[-2:] year_after = str(int(short_year) + 1) season = int("{0}{1}".format( short_year, year_after)) else: print "SS: Could not match dates" else: print "SS: Could not find {0}, defaulting to XXXX season format" # Using a hash so that each file gets the same episode number on every scan # The year must be included for seasons that run over a year boundary ep = int('%s%02d%02d%04d' % (year[-2:], month, day, abs(hash(file)) % (10**4))) tv_show = Media.Episode(show, season, ep, title, int(year)) tv_show.released_at = '%s-%02d-%02d' % (year, month, day) tv_show.parts.append(clean_files[file]) mediaList.append(tv_show) break else: print "SS: No match found for {0}".format(file) elif len(paths) >= 2: # Here we assume that it is in this format: League/Season show = paths[0] season = 0 # Look for the season in obvious ways or fail match = re.match('Season (\d{4})', paths[1]) if match: season = match.group(1) else: match = re.match('(\d{4})', paths[1]) if match: season = match.group(1) # Look for ALL the information we need in the filename - but trust what we have already found for file in clean_files: print "SS: Working on file | {0} |".format(file) for rx in regex_all_in_file_name: match = re.search(rx, file, re.IGNORECASE) if match: print "SS: matched regex | {0} |".format(rx) year = match.group('year') month = int(match.group('month')) day = int(match.group('day')) title = re.sub('[^0-9a-zA-Z]+', ' ', match.group('title')) # Using a hash so that each file gets the same episode number on every scan # The year must be included for seasons that run over a year boundary ep = int('%s%02d%02d%04d' % (year[-2:], month, day, abs(hash(file)) % (10**4))) tv_show = Media.Episode(show, season, ep, title, int(year)) tv_show.released_at = '%s-%02d-%02d' % (year, month, day) tv_show.parts.append(clean_files[file]) mediaList.append(tv_show) break # The following two loops should be used to match against other file names. for rx in regex_date_title_file_name: break for rx in regex_title_file_name: break # Stack the results. Stack.Scan(path, files, mediaList, subdirs)
def Scan(path, files, mediaList, subdirs, language=None, root=None): VideoFiles.Scan(path, files, mediaList, subdirs, root) paths = Utils.SplitPath(path) shouldStack = True logger.debug('=====================================================') logger.debug('- path:%s' % path) logger.debug('- files count:%s' % len(files)) logger.debug('- subdir count:%s' % len(subdirs)) for _ in subdirs: logger.debug(' * %s' % _) if len(paths) != 0: logger.debug('- paths[0] : %s' % paths[0]) if len(paths) == 1 and len(paths[0]) == 0: return name, year_path = VideoFiles.CleanName(paths[0]) tmp = os.path.split(path) logger.debug(tmp) season_num = None if len(tmp) == 2 and tmp[0] != '': try: match = re.search( r'(?P<season_num>\d{1,4})\s*((?P<season_title>.*?))?', tmp[1], re.IGNORECASE) if match: season_num = match.group('season_num') logger.debug('- season_num:%s', season_num) except: season_num = None logger.debug('- show(by path) name:%s year:%s', name, year_path) logger.debug('- files count : %s', len(files)) for i in files: tempDone = False try: file = os.path.basename(i) logger.debug(' * FILE : %s' % file) for rx in episode_regexps: match = re.search(rx, file, re.IGNORECASE) if match: season = int(match.group('season')) if match.group( 'season') is not None else 1 episode = int(match.group('ep')) if season_num is None: tv_show = Media.Episode(name, season, episode, '', year_path) else: tv_show = Media.Episode(name, season_num, episode, '', year_path) tv_show.display_offset = 0 tv_show.parts.append(i) mediaList.append(tv_show) logger.debug(' - APPEND by episode: %s' % tv_show) tempDone = True break if tempDone == False: for rx in date_regexps: match = re.search(rx, file) if match: year = match.group('year') year = int(year) + 2000 if len(year) == 2 else int( year) month = int(match.group('month')) day = int(match.group('day')) tmp = '%d-%02d-%02d' % (year, month, day) if season_num is None: tv_show = Media.Episode(name, year, None, None, None) else: tv_show = Media.Episode(name, season_num, None, None, None) #tv_show = Media.Episode(name, year, tmp, None, year) tv_show.released_at = tmp tv_show.parts.append(i) mediaList.append(tv_show) logger.debug(' - APPEND by date: %s' % tv_show) tempDone = True break if tempDone == False: logger.debug(' NOT APPEND!!') except Exception, e: logger.error(e)
def Scan(path, files, mediaList, subdirs, language=None, root=None): logging.basicConfig( filename= '/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Logs/Formula1.log', level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG) # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) # Run the select regexp for all media files. for i in files: logging.debug('Processing: %s' % i) postername = i[:-3] + "png" logging.debug("Downloading fake episode poster to: %s" % postername) if not os.path.exists(postername): try: urllib.urlretrieve( "https://raw.githubusercontent.com/potchin/PlexF1MediaScanner/master/episode_poster.png", postername) except IOError as e: logging.error("Unable to download poster: %s" % e) file = remove_prefix(i, root + '/') match = re.search(episode_regexp, file) if match: logging.debug("Regex matched file:" + file) # Extract data. show = 'Formula 1' year = int(match.group('year').strip()) show = "%s %s" % ( show, year) # Make a composite show name like Formula1 + yyyy location = match.group('location').replace("-", " ") # episode is just a meaningless index to get the different FP1-3, Qualifying, Race and other files to # be listed under a location i.e. Spain, which again is mapped to season number - as season can not contain a string episode = int(match.group('episode').strip()) # description will be the displayed filename when you browse to a location (season number) description = (location + " " + match.group('description')).replace( ".", " ") # i.e. # spain grand prix free practice 3 library_name = "%sx%s: %s %s" % (year, match.group('raceno'), location, match.group('session')) logging.debug("show: %s" % show) logging.debug("location: %s" % location) logging.debug("episode: %s" % episode) logging.debug("description: %s" % description) logging.debug("library_name: %s" % library_name) tv_show = Media.Episode( library_name, # show (inc year(season)) sessions[match.group( 'session' )], # season. Must be int, strings are not supported :( episode, # episode, indexed the files for a given show/location description, # includes location string and ep name i.e. Spain Grand Prix Qualifying year ) # the actual year detected, same as used in part of the show name logging.debug("tv_show created") tv_show.parts.append(i) logging.debug("part added to tv_shows") mediaList.append(tv_show) logging.debug("added tv_show to mediaList") else: logging.debug("Regex FAILED to match file: " + file) for s in subdirs: nested_subdirs = [] nested_files = [] for z in os.listdir(s): if os.path.isdir(os.path.join(s, z)): nested_subdirs.append(os.path.join(s, z)) elif os.path.isfile(os.path.join(s, z)): nested_files.append(os.path.join(s, z)) # This should be safe, since we're not following symlinks or anything that might cause a loop. Scan(s, nested_files, mediaList, nested_subdirs, root=root) # Stack the results. Stack.Scan(path, files, mediaList, subdirs)
def Scan(path, files, mediaList, subdirs, language=None, root=None): Log.debug('path: %s', path) Log.debug('files: %s', files) for subdir in subdirs: Log.info("[folder] " + os.path.relpath(subdir, root)) if files: # Scan for video files. VideoFiles.Scan(path, files, mediaList, subdirs, root) for idx, file in enumerate(files): try: Log.info('file: %s', file) # http://127.0.0.1:8111/api/ep/getbyfilename?apikey=d422dfd2-bdc3-4219-b3bb-08b85aa65579&filename=%5Bjoseole99%5D%20Clannad%20-%2001%20(1280x720%20Blu-ray%20H264)%20%5B8E128DF5%5D.mkv episode_data = HttpReq("api/ep/getbyfilename?filename=%s" % (urllib.quote(os.path.basename(file)))) if len(episode_data) == 0: continue if (try_get(episode_data, "code", 200) == 404): continue series_data = HttpReq( "api/serie/fromep?id=%d&nocast=1¬ag=1" % episode_data['id']) showTitle = series_data['name'].encode( "utf-8") #no idea why I need to do this. Log.info('show title: %s', showTitle) seasonNumber = 0 seasonStr = try_get(episode_data, 'season', None) if episode_data['eptype'] == 'Credits': seasonNumber = -1 #season -1 for OP/ED elif episode_data['eptype'] == 'Trailer': seasonNumber = -2 #season -2 for Trailer elif Prefs['SingleSeasonOrdering'] or seasonStr == None: if episode_data['eptype'] == 'Episode': seasonNumber = 1 elif episode_data['eptype'] == 'Special': seasonNumber = 0 else: seasonNumber = int(seasonStr.split('x')[0]) if seasonNumber <= 0 and episode_data[ 'eptype'] == 'Episode': seasonNumber = 1 elif seasonNumber > 0 and episode_data[ 'eptype'] == 'Special': seasonNumber = 0 if seasonNumber == 0 and Prefs['IncludeSpecials'] == False: continue if seasonNumber < 0 and Prefs['IncludeOther'] == False: continue #Ignore this by choice. if (try_get(series_data, "ismovie", 0) == 1 and seasonNumber >= 1): continue # Ignore movies in preference for Shoko Movie Scanner, but keep specials as Plex sees specials as duplicate Log.info('season number: %s', seasonNumber) episodeNumber = int(episode_data['epnumber']) Log.info('episode number: %s', episodeNumber) vid = Media.Episode(showTitle, seasonNumber, episodeNumber) Log.info('vid: %s', vid) vid.parts.append(file) mediaList.append(vid) except Exception as e: Log.error("Error in Scan: '%s'" % e) continue Stack.Scan(path, files, mediaList, subdirs) if not path: # If current folder is root folder Log.info("Manual call to group folders") subfolders = subdirs[:] while subfolders: # subfolder scanning queue full_path = subfolders.pop(0) path = os.path.relpath(full_path, root) reverse_path = list(reversed(path.split(os.sep))) Log.info('=' * 100) Log.info('Started subfolder scan: %s', full_path) Log.info('=' * 100) subdir_dirs, subdir_files = [], [] for file in os.listdir(full_path): path_item = os.path.join(full_path, file) if os.path.isdir(path_item): subdir_dirs.append(path_item) else: subdir_files.append(path_item) Log.info("Sub-directories: %s", subdir_dirs) Log.info("Files: %s", subdir_files) for dir in subdir_dirs: Log.info("[Added for scanning] " + dir) # Add the subfolder to subfolder scanning queue) subfolders.append(dir) grouping_dir = full_path.rsplit( os.sep, full_path.count(os.sep) - 1 - root.count(os.sep))[0] if subdir_files and (len(reverse_path) > 1 or subdir_dirs): if grouping_dir in subdirs: subdirs.remove( grouping_dir ) #Prevent group folders from being called by Plex normal call to Scan() Log.info("CALLING SCAN FOR FILES IN CURRENT FOLDER") Scan(path, sorted(subdir_files), mediaList, [], language, root) # relative path for dir or it will group multiple series into one as before and no empty subdirs array because they will be scanned afterwards. Log.info('=' * 100) Log.info('Completed subfolder scan: %s', full_path) Log.info('=' * 100)
def Scan(path, files, mediaList, subdirs, language=None, root=None): ### Root scan for OS information that i need to complete the Log function ### if path == "": Log("================================================================================") try: os_uname = "" for string in os.uname(): os_uname += string Log("os.uname(): '%s'" % os_uname) # (sysname, nodename, release, version, machine) # Log("Sys.platform: '%s'" % sys.platform) # Log("os.name: '%s'" % os.name) # 'posix', 'nt', 'os2', 'ce', 'java', 'riscos'.) Log("os.getcwd: '%s'" % os.getcwd()) # Current dir: /volume1/homes/plex Log("root folder: '%s'" % root if root is not None else "") except: pass ### Skip folder if empty ### if len(files) == 0: return ### Scan information and uild reverse_path array ### Log("================================================================================") Log("Scan: (root: '%s', path='%s', subdirs: %s, language: '%s')" % (root, path, str(subdirs), language)) VideoFiles.Scan(path, files, mediaList, subdirs, root) # relative_path = path.replace(root, " ") # /group/serie/season/ep folder reverse_path = Utils.SplitPath(relative_path) # Take top two as show/season, but require at least the top one. reverse_path.reverse() ### Skip unwanted folders ### for rx in ignore_dirs_re_findall: result = re.findall(rx, reverse_path[0]) if len(result): Log("Regex ignore_dirs_findall : match for '%s'" % reverse_path[0]) Log("[Folder] '%s'" % reverse_path[0], "Plex Media Scanner Custom - Skipped files") return ### bluray folder management ### # source: https://github.com/doublerebel/plex-series-scanner-bdmv/blob/master/Plex%20Series%20Scanner%20(with%20disc%20image%20support).py if len(reverse_path) >= 3 and reverse_path[0].lower() == 'stream' and reverse_path[1].lower() == 'bdmv': for rx in episode_re_search[0:-1]: match = re.search(rx, reverse_path[2], re.IGNORECASE) if match: episode = int(match.group('ep')) endEpisode = int(match.group('secondEp')) if match.groupdict().has_key('secondEp') and match.group( 'secondEp') else episode show, year = VideoFiles.CleanName(match.group('show')) if len(show) > 0: for ep in range(episode, endEpisode + 1): tv_show = Media.Episode(show, int(match.group('season')), ep, '', year) tv_show.display_offset = (ep - episode) * 100 / (endEpisode - episode + 1) for i in files: tv_show.parts.append(i) mediaList.append(tv_show) Log("show: '%s', year: '%s', season: '%2s', ep: %3s found using Bluray convention (bdmv/stream)" % ( show, xint(year), str(int(match.group('season'))), xint(episode))) return ### File loop for unwanted files, allow to use the number of actual files in folder accurately ### for file in files: # "files" is a list of media files full path filename = os.path.basename(file) # filename contain just the filename of the file ### Filter unwanted file extensions ### if file.split('.')[-1] in ignore_suffixes: # compare file extention to blacklist Log("'%s' ignore_suffixes: match" % filename) Log(file, "Plex Media Scanner Custom - ignored suffixes.log") files.remove(file) # in case we reprocess the lsit latter to precise matches or count number of files continue ### Filter trailers and sample files ### for rx in ignore_files_re_findall: match = re.findall(rx, file) if len(match): Log("'%s' ignore_files_findall: match" % filename) Log(file, "Plex Media Scanner Custom - Ignored files.log") files.remove(file) # in case we reprocess the list latter to precise matches, or count number of files break ### Check if folder is a season folder and remove it do reduce complexity ### folder_season = None for folder in reverse_path[ :-1]: # Doesn't thow errors but gives an empty list if items don't exist, might not be what you want in other cases for rx in specials_re_match + season_re_match: # in anime, more specials folders than season folders, so doing it first match = re.match(rx, folder, re.IGNORECASE) if match: folder_season = 0 if rx in specials_re_match else int(match.group( 'season')) # use "if var is | is not None:" as it's faster than "==None" and "if var:" is false if the variable is: False, 0, 0.0, "", () , {}, [], set() Log("Regex specials_regex/season_regex_match: Regex '%s' match for '%s', season: '%s'" % ( rx, folder, str(folder_season))) reverse_path.remove( folder) # All ways to remove: reverse_path.pop(-1), reverse_path.remove(thing|array[0]) break if match: break # Breaking second for loop doesn't exist parent for ### Clean folder name and get year if present ### misc, folder_year = VideoFiles.CleanName(reverse_path[0]) # Take folder year folder_show = clean_filename(reverse_path[0]) # Log("From folder, show: '%s', year: '%s'" % (folder_show, xint(folder_year))) # ### Main File loop to start adding files now #### for file in files: # "files" is a list of media files full path, File is one of the entries filename = os.path.basename(file) # filename is the filename of the file filename_no_ext = os.path.splitext(filename)[ 0] # filename_no_ext is the filename of the file, albeit with no extension misc, year = VideoFiles.CleanName( filename_no_ext) # Get the year before all '()' are stripped drom the filename without the extension ### Year? ### #if re.match('.+ \([1-2][0-9]{3}\)', paths[-1]): ep = clean_filename(filename_no_ext) # Strip () [], all, ep contain the serie name and ep number for now ### Cleanup episode filename If parent Folder contain serie name ### folder_use = False # Bolean to keep track if folder name in case it is included in the filename if folder_show is not None and not folder_show == "": # If containing folder exist or has name different from "_" (scrubed to "") misc = re.sub(folder_show, '', ep, flags=re.IGNORECASE).lstrip() # misc = ep.replace(folder_show, "") # remove cleaned folder name (if exist) from the show name junk = re.sub(folder_show.replace(" ", "").lower(), '', ep, flags=re.IGNORECASE).lstrip() # misc = ep.replace(folder_show, "") # remove cleaned folder name (if exist) from the show name # Log("ep: '%s', misc: '%s', junk: '%s'" % (ep, misc, junk)) if len(misc) < len(ep) or len(junk) < len( ep): # And remove the cleaned folder name from the now cleaned show, just in case the directory is off by things CleanName handles folder_use = True # indicate to latter use folder name since it is present in filename ep = folder_show + " 01" if misc == "" else misc # episode string name stripped of the folder name If nothing is left, take the folder (movie) ep_nb = ep if ep.rfind(" ") == -1 else ep.rsplit(' ', 1)[ 1] # If there is no space (and ep title) / If there is a space ep_nb is the last part hoping there is no episode title # Log ("#2 - ep: '%s'" % ep) # show, ep, title = ep.partition(match.group('ep')) # split keeping the separator, spare a line and keep the title ### Check for date-based regexps first. ### for rx in date_regexps: match = re.search(rx, ep) if match: # Make sure there's not a stronger season/ep match for the same file. try: for r in episode_regexps[:-1] + standalone_episode_regexs: if re.search(r, file): raise except: break year = int(match.group('year')) month = int(match.group('month')) day = int(match.group('day')) tv_show = Media.Episode(show, year, None, None, None) # Use the year as the season. tv_show.released_at = '%d-%02d-%02d' % (year, month, day) tv_show.parts.append(i) mediaList.append(tv_show) break if match: continue # Used "for ... else" before but needed each sub-section shifted, and want to be able to swap the order quickly # Log ("#3 - ep: '%s'" % ep) ### Check for standalone_episode_re_findall ### for rx in standalone_episode_re_findall: match = re.findall(rx, ep) if len(match): show, misc, year2, season, episode, misc, endEpisode, misc, episode_title = match[0] endEpisode = int(episode) if len(endEpisode) == 0 else int(endEpisode) episode = int(episode) add_episode_into_plex(mediaList, files, file, folder_show if folder_use or show == "" else show, season, int(episode), episode_title, year, endEpisode) Log( "show: '%s', year: '%s', season: '%s', ep: %s found using standalone_episode_re_findall on cleaned string '%s' gotten from filename '%s'" % ( folder_show if folder_use else show, xint(year), xint(season), xint(episode), ep, filename)) break # return if match: continue # Used "for ... else" before but needed each sub-section shifted, and want to be able to swap the order quickly # Log ("#4 - ep: '%s'" % ep) ### Check for episode_re_search ### for rx in episode_re_search: match = re.search(rx, ep, re.IGNORECASE) if match: show = clean_filename(match.group('show')) if not folder_use else folder_show season = int(match.group('season')) if folder_season is None else folder_season episode = int(match.group('ep')) endEpisode = int(match.group('secondEp')) if match.groupdict().has_key('secondEp') and match.group( 'secondEp') else episode add_episode_into_plex(mediaList, files, file, show, season, episode, "", year, endEpisode) Log( "show: '%s', year: '%s', season: '%s', ep: %s found using episode_re_search on cleaned string '%s' gotten from filename '%s' also ep_nb: '%s'" % ( show, xint(year), xint(season), xint(episode), ep, filename, ep_nb)) break if match: continue # Used "for ... else" before but needed each sub-section shifted, and want to be able to swap the order quickly ### Check for just_episode_re_search ### for rx in just_episode_re_search: match = re.search(rx, ep, re.IGNORECASE) if match: season = 1 if folder_season is None else folder_season episode = int(match.group('ep')) if folder_use: show = folder_show else: show = ep[:ep.find(match.group('ep'))].rstrip() # remove eveything from the episode number if show.rfind(" ") != -1 and show.rsplit(' ', 1)[1] in ["ep", "Ep", "EP", "eP", "e", "E"]: show = \ show.rsplit(' ', 1)[0] # remove ep at the end if show == "" or show.lower() in folder_show.lower(): show = folder_show # cut down forms of title point to folder anyway # In case of ep filename "EP 01 title of the episode" fallback to folder name add_episode_into_plex(mediaList, files, file, show, season, episode, "", year, None) Log( "show: '%s', year: '%s', season: '%s', ep: %3s found using just_episode_re_search on cleaned string '%s' gotten from filename '%s'" % ( show, xint(year), xint(season), xint(episode), ep, filename)) break if match: continue # Used "for ... else" before but needed each sub-section shifted, and want to be able to swap the order quickly # Log ("#6 - ep: '%s'" % ep) ### Check for AniDB_re_search ### for rx, offset in AniDB_re_search: match = re.search(rx, ep, re.IGNORECASE) if match: # if match.group('ep').isdigit(): episode = int( match.group('ep') ) # else: episode = 1 # for special, offset in [ ['SPECIAL',0], ['SP',0], ['S',0], ['OPENING',100], ['OP',100], ['NCOP',100], ['ENDING',150], ['ED',150], ['NCED',150], ['T',200], ['TRAILER',200], ['P',300], ['O',400] ]: # Removed ['OAV',0], ['OVA',0], as otherwise Asubi iku yo 13 OAV set as special ## if ep_nb.upper().startswith(special) or ep_nb.upper().startswith(special): # and len(ep_nb)<=4 and (ep_nb[ len(special): ].isdigit() or len(ep_nb)==2): episode = 1 if match.group('ep') == "" or not match.group('ep').isdigit() else int(match.group('ep')) episode = offset + episode Log( "show: '%s', year: '%s', season: '%s', ep: %3s found using AniDB_re_search on cleaned string '%s' gotten from filename '%s'" % ( folder_show, xint(year), "0", xint(episode), ep, filename)) add_episode_into_plex(mediaList, files, file, folder_show, 0, episode, "", year, None) break # else: # Log("AniDB regex ok but not catched afterwards - ep_nb: '%s', offset: '%d', string: '%s', file: '%s'" % (ep_nb, offset, ep_nb[ len(special):], file)) # Log("AniDB Folder: '%s', Filename: '%s', ep: '%s', ep_nb: '%s' misc: '%s', word: '%s'" % (reverse_path[0], filename, ep, ep_nb, misc, ep_nb[ len(special):]), "Plex Media Scanner Custom - Skipped files.log") # break if match: continue # Used "for ... else" before but needed each sub-section shifted, and want to be able to swap the order quickly ### Roman numbers ### doesn't work is ep title present match = re.match(roman_re_match, ep_nb, re.IGNORECASE) if match: ep_nb = roman_to_int(ep_nb) Log( "show: '%s', year: '%s', season: '%s', ep: %3s found using AniDB_re_search on cleaned string '%s' gotten from filename '%s'" % ( folder_show, xint(year), "1", xint(ep_nb), ep, filename)) add_episode_into_plex(mediaList, files, file, folder_show, 1, int(ep_nb), "", year, None) continue # Log ("#7 - ep: '%s'" % ep) ### No regular expression worked ### Log("*no show found for ep: '%s', eb_nb: '%s', filename '%s'" % (ep, ep_nb, filename)) Log("Folder: '%s', Filename: '%s', ep: '%s', ep_nb: '%s'" % (reverse_path[0], filename, ep, ep_nb), "Plex Media Scanner Custom - Skipped files.log")