def Scan(path, files, mediaList, subdirs): if len(files) >= 1: # Iterate through all the files for file in files: if (file.endswith("/info")): dir = os.path.dirname(file) infoFile = open(file).read() title = re.search('^T (.*)$', infoFile, re.M) if title: title = title.groups(1)[0] else: title = "Unnamed VDR recording" movie = Media.Movie(title) for ts_filename in sorted(os.listdir(dir)): if (ts_filename.endswith(".ts")): if (ts_filename.endswith("00001.ts")): movie.source = VideoFiles.RetrieveSource( dir + "/" + ts_filename) movie.parts.append(dir + "/" + ts_filename) if len(movie.parts) > 0: mediaList.append(movie)
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): #logging.basicConfig(filename='/tmp/vdrscanner.log',level=logging.DEBUG) if len(files) >= 1: # Iterate through all the files for file in files: if (file.endswith("/info")): dir = os.path.dirname(file) infoFile = open(file).read() title = re.search('^T (.*)$', infoFile,re.M) # accepted formats for Episode 3 of season 1, episode name "epname" # (3:22) epname # (3:22/s1) epname # (Ep 3:22) epname # (Ep 3:22/s1) epname # (Ep. 3:22) epname # (Ep. 3:22/s1) epname # # Both S and D lines are scanned. episode = re.search('^(?:S|D) \((?:Ep\.|Ep)?\s*(\d+)(?:\:\d+)?(?:\/s(\d+))?\)\.\s+(.*)$', infoFile, re.M) if episode and title: tvshow = True else: tvshow = False # some shows that lack episode info for some reason forceshow = re.search('^T (Ren and Stimpy|Die Ren & Stimpy Show|Simpsonit)', infoFile, re.M) if forceshow and title: tvshow = True if not tvshow: if title: title = title.groups(1)[0] else: title = "Unknown" #logging.debug('Title : %s' %title) movie = Media.Movie(title) for ts_filename in sorted(os.listdir(dir)): if (ts_filename.endswith(".ts")): if (ts_filename.endswith("00001.ts")): movie.source = VideoFiles.RetrieveSource(dir+"/"+ts_filename) movie.parts.append(dir+"/"+ts_filename) if len(movie.parts)>0: 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, 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, **kwargs): def strip_name_from_ts_file(tsfile): #Retrievess the programma name from a dreambox enigma2 file #This has the form of YYYYMMDD HHMM - Channel - Programmename.ts #code is borrowed from Enigma2 Movies.py by Quinten #https://forums.plex.tv/index.php/topic/68991-scanner-for-enigma2-ts-file #Also transforms the '_ ' to ': ' " base_name = os.path.splitext(os.path.basename(tsfile))[0] tmp_name = base_name.split(' - ' ,2)[2].strip() return re.sub(r'_ ',': ', tmp_name) if debug: logfile = open(debugfile, 'a') logfile.write("=======================================================\n") logfile.write(time.strftime("%c")) logfile.write(" --- Entering DREAMBOX DEBUG SCANNER\n") logfile.write("recvieved following parameters :\n") logfile.write("path parameter : ") logfile.write(str(path)) logfile.write('\n') logfile.write("files parameter : ") logfile.write(str(files)) logfile.write('\n') logfile.write("mediaList parameter : ") logfile.write(str(mediaList)) logfile.write('\n') logfile.write("subdirs parameter : ") logfile.write(str(subdirs)) logfile.write('\n') logfile.write("language parameter : ") logfile.write(str(language)) logfile.write('\n') logfile.write("root parameter : ") logfile.write(str(root)) logfile.write('\n') logfile.write("kwargs parameter : ") logfile.write(str(kwargs)) logfile.write('\n') logfile.write("========================================================\n") logfile.write(" START PRFOCESSING FILES SECTION \n ") year = '' genre = '' name = '' for scan_file in files: # Only process files having a ts extension (these are the movie files) if scan_file.endswith(".ts"): # chek then if we have the ts.meta meta file if os.path.isfile(scan_file + ".meta"): if debug: logfile.write(str("found ts.meta file : " + str(scan_file + ".meta") + "\n")) # lookup title and year from the ts.meta file meta = open(scan_file + ".meta", 'r') lines = meta.readlines() if debug: logfile.write("Content of the ") logfile.write(str(scan_file + ".meta" + "\n")) logfile.write(str(lines)) logfile.write("\n") name = lines[1].strip() if name: if debug: logfile.write(str("substracted the programname " + (name) + "\n")) else: # programma name is empty in the ts.meta file, so we take it from the filename name = strip_name_from_ts_file(tsfile=scan_file) if debug: logfile.write(str("no title in ts.meta file found, abstracted form filename : " + (name) + "\n")) # line 3 in the meta file contains multiple formats. In this directory we # assume onlu movies are to be processed # Most common format we have encounterd yet : # <genre>.<year>.<short description> where all fields ar not always there # <year>.<genre>.<short description> # <descripton><(year)><(duration)> # empty # <free text> if lines[2].strip(): # we do have content if re.match(r'\d{4}\.', lines[2]): if debug: logfile.write("first RegExp matches, first field is the year\n") line_array = lines[2].split('.', 2) elements = len(line_array) year = line_array[0] if elements >= 2: genre = line_array[1] else: genre = '' if elements >= 3: short_info = line_array[2] else: short_info = '' elif re.search(r'\.\d{4}\.', lines[2]): if debug: logfile.write("Second RegExp matches, second field is the year\n") line_array = lines[2].split('.', 2) elements = len(line_array) genre = line_array[0] year = line_array[1] if elements >= 3: short_info = line_array[2] else: short_info = '' elif re.search(r'\(\d{4}\)', lines[2]): if debug: logfile.write("Third RegExp matches, year after info\n") pat = re.compile(r'\(\d{4}\)') res = pat.search(lines[2]) short_info = lines[2][0:res.start()-1] year = lines[2][res.start()+1:res.end()-1] genre = '' else: if debug: logfile.write("line not empty, but no match found\n") # we handle this as short info genre = '' year = '' short_info = lines[2] else: # empty line if debug: logfile.write("empty line\n") year = '' genre = '' short_info = '' else: name = strip_name_from_ts_file(tsfile=scan_file) year = '' if debug: logfile.write(str("the year of the movie is " + str(year) + "\n")) logfile.write(str("the genre of the movie is " + str(genre) + "\n")) logfile.write(str("the info of the movie is " + str(short_info) + "\n")) movie = Media.Movie(name, year) movie.source = VideoFiles.RetrieveSource(scan_file) movie.parts.append(scan_file) if debug: logfile.write("========================================\n") logfile.write(str(movie)) logfile.write("\n") logfile.write("========================================\n") mediaList.append(movie) if debug: logfile.write(" ========================================================================\n") logfile.close()
def Scan(path, files, mediaList, subdirs): '''Scan for SageTV Movies This is called by PLEX for every directory and subdirectories in the import folder. @param path path relative to root folder @param files empty list @param mediaList show should be added here @param subdirs list of subdirs under path ''' mylog.info('***** Entering SageTV Movie Scanner.Scan *****') mylog.debug('Path: ' + (path if path else 'ROOT')) # create sagex obj for SageTV API call sagexHost = sageplexcfg.getSagexHost() sageapi = sageplex.sagex.SageX(sagexHost) # scans the current dir and return the list files for processing. # files that have already been processed will not be returned. mylog.debug('Calling VideoFiles.Scan() ...'); VideoFiles.Scan(path, files, mediaList, subdirs, None) # Scan for video files. if not files: mylog.info('No files returned, done') mylog.info('') # done write empty line so we have good separator for next time return # stat we track while in loop stat = { 'item': 0, 'size': len(files), 'added': 0} # interate over all files found in VideoFiles.Scan above for i in files: # i contains the full path to the file stat['item'] += 1 mylog.info('[%d/%d] Processing %s', stat['item'], stat['size'], i) filename = os.path.basename(i) (fname, fext) = os.path.splitext(filename) # if the extension is in our list of acceptable sagetv file extensions, then process if not fext.lower() in sageplexcfg.getScannerExt(): mylog.info('wrong extension, skipping: %s', fext) continue # Get SageTV media info from sagex via HTTP call mylog.debug('Getting media info from SageTV ...') mf = sageapi.getMediaFileForName(filename) if not mf: # this would happen if there is a file on the Plex import # directory but that file is not yet in Sage's DB mylog.error("No media info from SageTV: %s", filename) continue # retrieving the airing/show field that should always exist airing = mf.get('Airing') if not airing: mylog.error('no Airing field, skipping file'); continue showMF = airing.get('Show') if not showMF: mylog.error('no [Airing][Show] field, skipping file'); continue # check to see if TV show or not if not isRecordedMovie(mf, airing, showMF): continue showTitle = showMF.get('ShowTitle').encode('UTF-8') mylog.debug('ShowTitle: %s', showTitle) showYear = showMF.get('ShowYear').encode('UTF-8') mylog.debug('ShowYear: %s', showYear) if not showYear: showYear = '' # now we create the Media.Movie object representing this # movie so we can add it to PLEX. movie = Media.Movie(showTitle, showYear) movie.source = VideoFiles.RetrieveSource(filename) # need to handle mutliple recordings for the # same physical show i.e. -0.mpg, -1.mpg, -2.mpg m_seg = mf.get('NumberOfSegments') if (m_seg > 1): # if show have more than one segment, see if we need to # add this to an existing mediaFile object mylog.info("Media has more than 1 segment: %s", m_seg) # first lookup the show in the current added mediaList, if # found, this means we've processed existing segments of # the show, so just add the additional segments mFound = False for mItem in mediaList: # is this the right show if (mItem.name != showTitle or mItem.year != showYear): continue # found the show, add file to show mItem.parts.append(i) # add to end mItem.parts.sort() # sort file list lexically mylog.info('Added to existing mediaList obj: %s', mItem) # handled, so break out of search loop stat['added'] += 1 mFound = True break if mFound: # multi-segment and used an existing mediaList object, # so done, go to next file. the current tv_show object # is discarded. continue # only one segment, or multi-segment but first time, # add the file to the new movie object movie.parts.append(i) mylog.info("Adding movie to mediaList") mediaList.append(movie) stat['added'] += 1 # END "for i in files" mylog.info('Total: %d of %d added to mediaList', stat['added'], stat['size']) # only need to do this once at end, not for every file if stat['added']: mylog.info("Performing Stack.Scan() ...") Stack.Scan(path, files, mediaList, subdirs) mylog.info('') # done write empty line so we have good separator for next time