def parse_filename(self, filepath): ''' Uses PTN to get as much info as possible from path filepath (str): absolute path to movie file Parses parent directory name first, then file name if folder name seems incomplete. Returns dict of metadata ''' dirname = os.path.split(filepath)[0].split(os.sep)[-1] logging.info( 'Parsing directory name for movie information: {}.'.format( dirname)) meta_data = PTN.parse(dirname) for i in ('excess', 'episode', 'episodeName', 'season', 'garbage', 'website'): meta_data.pop(i, None) if len(meta_data) > 3: meta_data["release_name"] = dirname logging.info('Found {} in filename.'.format(meta_data)) else: logging.debug( 'Parsing directory name does not look accurate. Parsing file name.' ) filename = os.path.basename(filepath) meta_data = PTN.parse(filename) logging.info('Found {} in file name.'.format(meta_data)) if len(meta_data) < 2: logging.warning( 'Little information found in file name. Movie may be incomplete.' ) meta_data['release_title'] = filename title = meta_data.get('title') if title and title[-1] == '.': meta_data['title'] = title[:-1] # Make sure this matches our key names if 'year' in meta_data: meta_data['year'] = str(meta_data['year']) meta_data['videocodec'] = meta_data.pop('codec', None) meta_data['audiocodec'] = meta_data.pop('audio', None) if meta_data.get('edition'): meta_data['edition'] = ' '.join(meta_data['edition'].sort()) qual = meta_data.pop('quality', '') for source, aliases in core.CONFIG['Quality']['Aliases'].items(): if any(a.lower() == qual.lower() for a in aliases): meta_data['source'] = source break meta_data['source'] = meta_data.get('source', None) meta_data['releasegroup'] = meta_data.pop('group', None) return meta_data
def parse_filename(self, data): ''' Parses filename for release information :param data: dict movie info PTN only returns information it finds, so we start with a blank dict of keys that we NEED to have, then update it with PTN's data. This way when we rename the file it will insert a blank string instead of throwing a missing key exception. Might eventually replace this with Hachoir-metadata Returns dict of parsed data ''' filename = data['filename'] path = data['path'] # This is our base dict. Contains all neccesary keys, though they can all be empty if not found. metadata = { 'title': '', 'year': '', 'resolution': '', 'releasegroup': '', 'audiocodec': '', 'videocodec': '', 'source': '', 'imdbid': '' } titledata = PTN.parse(os.path.basename(filename)) # this key is useless if 'excess' in titledata: titledata.pop('excess') if len(titledata) <= 2: logging.info( u'Parsing filename doesn\'t look accurate. Parsing parent folder name.' ) path_list = path.split(os.sep) titledata = PTN.parse(path_list[-1]) logging.info(u'Found {} in parent folder.'.format(titledata)) else: logging.info(u'Found {} in filname.'.format(titledata)) # Make sure this matches our key names if 'codec' in titledata: titledata['videocodec'] = titledata.pop('codec') if 'audio' in titledata: titledata['audiocodec'] = titledata.pop('audio') if 'quality' in titledata: titledata['source'] = titledata.pop('quality') if 'group' in titledata: titledata['releasegroup'] = titledata.pop('group') metadata.update(titledata) return metadata
def analyze(input, name, season='', episode='', resolution='', quality=''): matches = [] data = [] # If for some reason there is not magnet or torrent link but result is shown remove it. for torrent in input: if torrent.has_key('Magnet') or torrent.has_key('Torrent'): data.append(torrent) for torrent in data: # Has key is used to check if PTN can extract certain info from filename for filtering results. # (PTN creates a dict with found parameters as keys). key1 = PTN.parse(torrent['Episode Name']).has_key('season') key2 = PTN.parse(torrent['Episode Name']).has_key('episode') key3 = PTN.parse(torrent['Episode Name']).has_key('resolution') key4 = PTN.parse(torrent['Episode Name']).has_key('quality') # f-i checks if value for parameter is entered (the only that can't be blank is show title). f = season != '' g = episode != '' h = resolution != '' i = quality != '' a = PTN.parse(torrent['Episode Name'])['title'].lower() != name.lower() # Checks if a value for parameter is entered and matches PTN result (if data is available). b = True c = True d = True e = True if key1: b = PTN.parse(torrent['Episode Name'])['season'] != season if key2: c = PTN.parse(torrent['Episode Name'])['episode'] != episode if key3: d = PTN.parse(torrent['Episode Name'])['resolution'].lower( ) != resolution.lower() if key4: e = PTN.parse( torrent['Episode Name'])['quality'].lower() != quality.lower() n1 = (not key1) and f n2 = (not key2) and g n3 = (not key3) and h n4 = (not key4) and i # If parameter exists and required add torrent to matches. if not (a or (b and f) or (c and g) or (d and h) or (e and i)): matches.append(torrent) # If parameter required but does not exist remove the value from matches (this required because of the way PTN works). if (n1 or n2 or n3 or n4) and matches != []: matches.remove(torrent) return matches
def parse_filename(self, filepath): ''' Uses PTN to get as much info as possible from path filepath (str): absolute path to file Returns dict of metadata ''' logging.info( 'Parsing filename for movie information: {}.'.format(filepath)) titledata = PTN.parse(os.path.basename(filepath)) # remove usless keys before measuring length for i in ('excess', 'episode', 'episodeName', 'season', 'garbage', 'website'): titledata.pop(i, None) if len(titledata) < 3: logging.debug( 'Parsing filename does not look accurate. Parsing parent folder name.' ) fname = os.path.split(filepath)[0].split(os.sep)[-1] titledata = PTN.parse(fname) titledata['release_title'] = fname logging.info('Found {} in parent folder.'.format(titledata)) if len(titledata) < 2: logging.warning( 'Little information found in parent folder name. Movie may be incomplete.' ) else: titledata['release_name'] = os.path.basename(filepath) logging.info('Found {} in filename.'.format(titledata)) title = titledata.get('title') if title and title[-1] == '.': titledata['title'] = title[:-1] # Make sure this matches our key names if 'year' in titledata: titledata['year'] = str(titledata['year']) titledata['videocodec'] = titledata.pop('codec', None) titledata['audiocodec'] = titledata.pop('audio', None) qual = titledata.pop('quality', None) for source, aliases in core.CONFIG['Quality']['Aliases'].items(): if any(a.lower() == qual.lower() for a in aliases): titledata['source'] = source break titledata['source'] = titledata.get('source', None) titledata['releasegroup'] = titledata.pop('group', None) return titledata
def parse_filename(self, filepath): ''' Uses PTN to get as much info as possible from path filepath: str absolute path to file Returns dict of Metadata ''' logging.info(u'Parsing {} for movie information.'.format(filepath)) # This is our base dict. Contains all neccesary keys, though they can all be empty if not found. metadata = { 'title': '', 'year': '', 'resolution': '', 'releasegroup': '', 'audiocodec': '', 'videocodec': '', 'source': '', 'imdbid': '' } titledata = PTN.parse(os.path.basename(filepath)) # this key is useless if 'excess' in titledata: titledata.pop('excess') if len(titledata) < 2: logging.info( u'Parsing filename doesn\'t look accurate. Parsing parent folder name.' ) path_list = os.path.split(filepath)[0].split(os.sep) titledata = PTN.parse(path_list[-1]) logging.info(u'Found {} in parent folder.'.format(titledata)) else: logging.info(u'Found {} in filename.'.format(titledata)) title = titledata.get('title') if title and title[-1] == '.': titledata['title'] = title[:-1] # Make sure this matches our key names if 'codec' in titledata: titledata['videocodec'] = titledata.pop('codec') if 'audio' in titledata: titledata['audiocodec'] = titledata.pop('audio') if 'quality' in titledata: titledata['source'] = titledata.pop('quality') if 'group' in titledata: titledata['releasegroup'] = titledata.pop('group') metadata.update(titledata) return metadata
def parse_media_info(name): parsed = PTN.parse(name) if parsed.get('episode'): return parsed # additional processing required seasonsmatch = re.search( "(.*)[ .]([sS][0-9]{1,2}-[sS][0-9]{1,2}|COMPLETE)", name) if seasonsmatch: parsed['title'] = seasonsmatch.group(1).replace('.', ' ') parsed['seasons'] = seasonsmatch.group(2) return parsed seasonmatch = re.search("(.*)[ .][sS]([0-9]{1,2})", name) if seasonmatch: parsed['title'] = seasonmatch.group(1).replace('.', ' ') parsed['season'] = int(seasonmatch.group(2)) return parsed if parsed.get('year'): # more likely a movie if not an episode moviematch = re.match("(.*)([1-2]{1}[0-9]{3})[ .]", name) if moviematch: parsed['title'] = moviematch.group(1).replace('.', ' ').strip() return parsed
def analyze_file(self, file): file_type = file.get('type') if file_type == 'video': title = file['title'] parsed = PTN.parse(title) parsed_title = parsed.get('title') parsed_year = parsed.get('year') parsed_season = parsed.get('season') parsed_episode = parsed.get('episode') if parsed_season and parsed_episode: file['search_type'] = 'tv' file['parsed_title'] = parsed_title file['parsed_year'] = parsed_year file['parsed_season'] = parsed_season file['parsed_episode'] = parsed_episode elif parsed_title is not None and parsed_year: file['search_type'] = 'movie' file['parsed_title'] = parsed_title file['parsed_year'] = parsed_year else: file['search_type'] = 'skip' else: file['search_type'] = 'skip' return file
def fuzzy_title(releases, titles, year='\n'): ''' Score and remove releases based on title match releases (list[dict]): scene release metadata to score and filter titles (list): titles to match against year (str): year of movie release <optional -default '\n'> If titles is an empty list every result is treated as a perfect match Matches releases based on release_title.split(year)[0]. If year is not passed, matches on '\n', which will include the entire string. Iterates through releases and removes any entry that does not fuzzy match 'title' > 70. Adds fuzzy_score / 20 points to ['score'] Returns list[dict] ''' logging.info('Checking title match.') reject = 0 if titles == [] or titles == [None]: logging.debug( 'No titles available to compare, scoring all as perfect match.') for result in releases: if result['reject_reason']: reject += 1 continue result['score'] += 20 else: for result in releases: if result['reject_reason']: reject += 1 continue if result['type'] == 'import': logging.debug( '{} is an Import, sorting as a perfect match.'.format( result['title'])) result['score'] += 20 continue rel_title_ss = result.get('ptn', PTN.parse(result['title']))['title'] logging.debug( 'Comparing release substring {} with titles {}.'.format( rel_title_ss, titles)) matches = [_fuzzy_title(rel_title_ss, title) for title in titles] if any(match > 70 for match in matches): result['score'] += int(max(matches) / 5) else: logging.debug( '{} best title match was {}%, removing search result.'. format(result['title'], max(matches))) result[ 'reject_reason'] = 'mismatch title (best match was {}%)'.format( max(matches)) reject += 1 logging.info('Keeping {} releases.'.format(len(releases) - reject)) return releases
def update_available_eps(url, show_id): db, cursor = get_db() #print(url) ep = requests.get('%s%s' % (config.get("eztv", "host"), url)) eps = BeautifulSoup(ep.text, "lxml") for episode in eps.find_all('tr'): ep_string = str(episode.find('a', class_="epinfo")) parsed_data = PTN.parse(ep_string) quality = parsed_data['quality'] if 'quality' in parsed_data else 'Unknown' resolution = parsed_data['resolution'] if 'resolution' in parsed_data else 'Unknown' info = re.findall(episode_info_regex, ep_string) if len(info) > 0: season = info[0][1] number = info[0][2] else: continue ep_id = re.findall(episode_id_regex, ep_string) if len(ep_id) > 0: episode_id = ep_id[0] magnet = episode.find('a', class_="magnet") if magnet is not None: magnet = magnet['href'] cursor.execute("INSERT INTO episodes (`show_id`, `episode_id`, `number`, `season`, `magnet`, `downloaded`, `quality`, `resolution`) VALUES (%s, %s, %s, %s, %s, 0, %s, %s) ON DUPLICATE KEY UPDATE magnet = %s, quality = %s, resolution = %s", (show_id, episode_id, number, season, magnet, quality, resolution, magnet, quality, resolution, )) db.commit()
def store_show(info): shows = [] show = PTN.parse(info) shows.append(show) #Checking for shows in memory, if no shows found add new list with one new show. try: file = open('myshows.txt', 'rb') except IOError: file = open('myshows.txt', 'wb') try: file = open('myshows.txt', 'rb') storedshows = pickle.load(file) except EOFError: file = open('myshows.txt', 'wb') pickle.dump(shows, file) storedshows = shows # Checking if show exists in memory, if not add. if not any(value['title'] == show['title'] for value in storedshows): file = open('myshows.txt', 'rb') shows = pickle.load(file) shows.append(show) file = open('myshows.txt', 'wb') pickle.dump(shows, file) # Return the list of shows. file = open('myshows.txt', 'rb') return pickle.load(file) file.close()
def score_year(releases, year): ''' Increase score for each group of 'words' match releases (list[dict]): scene release metadata to score and filter year (int): expected year Iterates through releases and adds 20 points to every entry with exact year match Keeps releases without year or 1 year higher or lower. Returns list[dict] ''' logging.info('Checking year match.') reject = 0 for r in releases: if r['reject_reason']: reject += 1 continue if 'ptn' not in r: r['ptn'] = PTN.parse(r['title']) if 'year' in r['ptn']: if r['ptn']['year'] == year: r['score'] += 20 if abs(year - r['ptn']['year']) > 1: reject += 1 r['reject_reason'] = 'Year mismatch' return releases
def handle_comic_file(comic_file): print('Handling comic file', comic_file) superdir = os.path.dirname(comic_file) name, ext = os.path.splitext(os.path.basename(comic_file)) comic_parse = PTN.parse(name) print(comic_parse) # The parser matches comic book title and issue number both into 'title' key. # Compile the regex that matches for comic issue numbers. issue_regex = re.compile('(\d{1,3}(\.\d*)*\s*$)') # Split the title by regex matching. title_split = issue_regex.split(comic_parse['title']) # Strip trailing spaces from the title. title = title_split[0].strip() # If the split found a match and actually split, make the second half the issue number. if len(title_split) >= 2: issue = ' ' + title_split[1].strip() else: issue = '' # A Free Comic Book Day issue has no issue number, so it replaces the issue number value. if 'fcbd' in comic_parse: if comic_parse['fcbd']: issue = ' FCBD' if 'year' in comic_parse: year = ' (' + str(comic_parse['year']) + ')' else: year = '' # Construct the renamed filename. rename = title + issue + year comic_file_renamed = os.path.join(superdir, rename+ext) print('Renaming', comic_file, '->', comic_file_renamed) shutil.move(comic_file, comic_file_renamed) move_or_overwrite(comic_file_renamed, dest_comic, os.path.join(dest_comic, rename+ext))
def __init__(self, fullpath, fullname): self.fileName = fullname self.movieName = os.path.splitext(fullname)[ 0] #Remove extension from name self.filePath = fullpath self.seriesType = False parsedFile = PTN.parse(self.movieName) self.parsedGroup, self.parsedSeason, self.parsedEpisode, self.parsedYear = "", "", "", "" parsedMovieName = parsedFile['title'] print(self.fileName) match = input(parsedMovieName + '?') if match != "": parsedMovieName = match if 'group' in parsedFile: self.parsedGroup = parsedFile['group'].replace("[", "").replace( "]", "") #Remove [] from YTS.AM if 'season' in parsedFile: self.seriesType = True self.parsedSeason = str(parsedFile['season']).rjust(2, '0') self.parsedEpisode = str(parsedFile['episode']).rjust(2, '0') if 'year' in parsedFile: self.parsedYear = parsedFile['year'] self.findSub = parsedMovieName if self.parsedYear != "": self.findSub = self.findSub + ' ' + str(self.parsedYear) return
def __init__(self, name): ptn_dict = PTN.parse(name) key_list = [ "resolution", "codec", "season", "episode", "bitDepth", "audio", "quality", "encoder", "title", "year", "remux", ] for key in key_list: setattr(self, key, ptn_dict.get(key)) # Write REMUX instead of Blu-Ray self.quality = "REMUX" if self.remux else self.quality self.sortkeys = { "se": self.season, "ep": self.episode, "res": self.resolution, "title": self.title, "year": self.year, }
def getName(name): #Returns the title of a Show or Movie try: return PTN.parse(name)['title'] except KeyError: return "Unsorted"
def test_all_raw(self): json_input = os.path.join(os.path.dirname(__file__), "files/input.json") with open(json_input) as input_file: torrents = json.load(input_file) json_output = os.path.join(os.path.dirname(__file__), "files/output_raw.json") with open(json_output) as output_file: expected_results = json.load(output_file) self.assertEqual(len(torrents), len(expected_results)) excess_elements = 0 for torrent, expected_result in zip(torrents, expected_results): print("Test: {}".format(torrent.encode("utf-8", "replace"))) result = PTN.parse(torrent, standardise=False) if "excess" in result: print("excess: {}".format( str(result["excess"]).encode("utf-8", "replace"))) if isinstance(result["excess"], list): excess_elements += len(result["excess"]) else: excess_elements += 1 for key in expected_result: self.assertIn(key, result, torrent.encode("utf-8", "replace")) self.assertEqual(expected_result[key], result[key], key) for key in result.keys(): if key not in ("encoder", "excess", "site"): # Not needed in tests self.assertIn(key, expected_result) print("Excess elements total: {}".format(excess_elements))
def destination_guess(file): def _is_match(a, b): return a['season'] == b['season'] and a['episode'] == b['episode'] def _append_moved(mlist, mdata): mlist.append({'season': mdata['season'], 'episode': mdata['episode']}) metadata = PTN.parse(file.name) if not _is_tv_episode(metadata): print(f' x Not TV: missing title, season and/or episode {metadata}') return None title = metadata['title'].title() moved_episodes = TV_MOVED.get(title) if moved_episodes is None: TV_MOVED[title] = [] for entry in TV_MOVED[title]: if _is_match(metadata, entry): return None _append_moved(TV_MOVED[title], metadata) return TV_BASE.joinpath(metadata['title'].title())
def scan(root, name): ext = [".3g2", ".3gp", ".amv", ".asf", ".asx", ".avi", ".drc", ".flv", ".f4v", ".f4p", ".f4a", ".f4b", ".mkv", ".mov", ".qt", ".mp4", ".m4p", ".m4v", ".mpg", ".mp2", ".mpeg", ".mpe", ".mpv", ".m2v", ".ogv", ".rm", ".rmvb", ".svi", ".webm", ".wmv"] #found = [] # array for all the files found cache = {} # cache for imdb json results info = [] # item info #def generate(): # for root, dirs, files in os.walk(path): # for name in files: if name.endswith(tuple(ext)): file_location = root.split("\\") # ['E:', 'TV-Series', 'Top Gear', 'Season 1'] foldername = "" if (len(file_location)-1 >= 0): temp = file_location[len(file_location)-1] # current folder name - either season name or title foldername = temp if ("season" not in temp.lower()) else file_location[len(file_location)-2] info = PTN.parse(name) # Check if title exists, if not - use folder name instead if (info["title"] == ""): info["title"] = foldername # Add item type - movie or tv-show info["type"] = "tv_shows" if ("episode" in info) else "movies" # Add file location #info["location"] = root # Remove extension from title in case it stays there for extension in ext: info["title"] = re.sub(extension.lower(), '', info["title"]) # Quick-fix for movies - add empty episode and season values if ("episode" not in info): info["episode"] = "" if ("season" not in info): info["season"] = "" # Save to the found_on_imdb key info["found_on_imdb"] = imdbJSONResponse(root + "\\" + name, info["title"], info["type"], info["season"], info["episode"], cache, 5) # Add to the resulting list #found.append(info) #return json.dumps(found) result = json.dumps(info) + "\n" if info else '' return result
def solveName(self, filePath, fileName): parsedGroup, parsedSeason, parsedEpisode, parsedYear = "", "", "", "" assetFileName = os.path.splitext(fileName)[ 0] #Remove extension from name assetIsSeries = False parsedFile = PTN.parse(assetFileName) parsedAssetName = parsedFile['title'] #print (self.assetFileName) if 'group' in parsedFile: parsedGroup = parsedFile['group'].replace("[", "").replace( "]", "") #Remove [] from YTS.AM if 'season' in parsedFile: assetIsSeries = True parsedSeason = str(parsedFile['season']).rjust(2, '0') parsedEpisode = str(parsedFile['episode']).rjust(2, '0') if 'year' in parsedFile: parsedYear = parsedFile['year'] # Add imdb page tt number here assetAttributes = { "dizi": assetIsSeries, "isim": parsedAssetName, "grup": parsedGroup, "sezon": parsedSeason, "bölüm": parsedEpisode, "yıl": str(parsedYear), "dosyaisim": assetFileName, "dosyadizin": filePath, "imdbsayfa": "" } return assetAttributes #Returns Dictionary
def checklatest(show): title = PTN.parse(show)['title'] # Formatting the name for TV.com -name must be accurate ("ie daredevil= marvels daredevil). output = '' fshow = title.replace(' ', '-') # Getting search engine (TV.com). resp = requests.get("http://www.tv.com/shows/" + fshow) soup = BeautifulSoup( resp.content, "lxml", ) result = soup.find('p', {'class': 'highlight_season'}).text.strip('\n') data = [int(s) for s in result.split() if s.isdigit()] # Formatting for normal S##E## if data[0] < 10: output += 'S' + '0' + str(data[0]) else: output += 'S' + str(data[0]) if data[1] < 10: output += 'E' + '0' + str(data[1]) else: output += 'E' + str(data[1]) return show + ' ' + output
def test_parser(self): json_input = os.path.join(os.path.dirname(__file__), 'files/input.json') with open(json_input) as input_file: torrents = json.load(input_file) json_output = os.path.join(os.path.dirname(__file__), 'files/output.json') with open(json_output) as output_file: expected_results = json.load(output_file) self.assertEqual(len(torrents), len(expected_results)) for torrent, expected_result in zip(torrents, expected_results): print("Test:" + torrent) result = PTN.parse(torrent) print (f"\nIn:{torrent}\nEx:{expected_result}\n\n") for key in expected_result: if not expected_result[key]: self.assertNotIn(key, result) else: self.assertIn(key, result) result1 = result[key] if key == 'excess' and type(result1) == list: result1 = ', '.join(result1) self.assertEqual(result1, expected_result[key])
def file_type_is_video(filename): """ function which identify if files is a video files if normaly we use the file extension to know if it's a video. what about folder containing video files ? this function use dictionnary keys of the PTN library to know if it's a video or not """ metadata = PTN.parse(filename) if 'codec' in metadata.keys(): if 'resolution' in metadata.keys(): if 'quality' in metadata.keys(): return True elif 'quality' in metadata.keys(): return True elif 'resolution' in metadata.keys(): if check_video_extension(filename): return True else: return False elif 'quality' in metadata.keys(): if check_video_extension(filename): return True else: return False
def parse_info_from_name(self, name): if name: info = dict_2_default_dict(PTN.parse(name)) year = info['year'] if info['year'] else None title = get_title_from_name(name) quality = info['quality'] if info['quality'] else None return dict_2_default_dict({**info, "year": year, "title": title, "quality": quality}) return dict_2_default_dict({"year": None, "title": None, "quality": None})
def get_episode_info(fn): try: parsed = PTN.parse(fn) episode_num = parsed.get("episode") season_num = parsed.get("season") year = parsed.get("year") return [season_num, episode_num, year] except TypeError: return [None, None, None]
def __init__(self, name): self.ptn_parsed_dict = PTN.parse(name, standardise=False) self.metas2get = ['resolution', 'codec', 'bitDepth', 'audio', 'quality', 'encoder'] for obj in self.metas2get: current_obj_value = self.ptn_parsed_dict.get(obj) if self.ptn_parsed_dict.get(obj): setattr(self, obj, current_obj_value)
def parse_name(self): info = PTN.parse(self.path.name) self._get_title_if_not_set(info) self._get_year_if_not_set(info) if info.get("season"): self.season = str(info.get("season")).zfill(2) self.episode = str(info.get("episode")).zfill(2) print("Title and year from filename are:") print("%s [%s]" % (self.title, self.year))
def list_top100(url='/precompiled/data_top100_207.json'): url = _host + url data = requests.get(url).json() movies = {} for movie in data: se = movie['seeders'] le = movie['leechers'] id = movie['id'] name = movie['name'] info = PTN.parse(name) quality = info['quality'] if 'quality' in info else 'Unknown' resolution = info['resolution'] if 'resolution' in info else 'Unknown' year = info['year'] if 'year' in info else 'XXXX' title = info['title'].strip().rstrip('.').lower() lookup_title = '%s %s' % (title, year) ih = movie['info_hash'] magnet = 'magnet:?xt=urn:btih:' + ih + print_trackers() if lookup_title not in movies: movies[lookup_title] = {} movies[lookup_title][id] = { 'hash': hash(lookup_title), 'title': title, 'id': id, 'magnet': magnet, 'le': le, 'se': se, 'year': year, 'raw': name, 'quality': quality, 'resolution': resolution, 'parse': info, 'good': (quality.lower() in ('brrip', 'bluray', 'webrip', 'web-dl')) and resolution == '1080p', 'decent': (quality.lower() in ('brrip', 'bluray', 'webrip', 'web-dl')) and resolution == '720p' } return movies
def get_movie(my_call, search_lst): for item, var in my_call.items(): search_me = str(var[b'name'], 'utf-8') new_srch = PTN.parse(search_me.lower()) if 'episode' in new_srch and 'season' in new_srch: continue choice = process.extractOne(new_srch['title'], search_lst) if choice[1] > 95: print(choice) print(item, var)
def extract_movie_info(self): """ If package PTN (parse torrent name) fails to detect a title and a year, a batch of homemade regular expressions are deployed to give it a try. """ movie_info = PTN.parse(self.title) try: self.title = movie_info["title"] self.year = movie_info["year"] except KeyError: self._parse_movie_name()
def get_movies(): with requests.Session() as s: r = s.post(url_login, data=payload_login) r = s.get(url_top_movies) data = r.text soup = BeautifulSoup(data, 'html.parser') body_element = soup.find('table', {'class': 'torrentlist'}) movies = body_element.find_all('td', {'align': 'left'}) films = [] for movie in movies: if movie.a is not None and movie.a.b is not None: title = movie.a.b.text link = movie.a['href'] id = link.split('=')[1] movie = PTN.parse(title)["title"] film = dict() film["year"] = 1933 film["movieID"] = id film["title"] = title film["movie"] = movie film["imdb"] = "9.0" film["rotten"] = "8.3" film["metacritic"] = "8.7" film[ "plot"] = "When the menace known as the Joker emerges from his mysterious past, he wreaks havoc and chaos on the people of Gotham, the Dark Knight must accept one of the greatest psychological and physical tests of his ability to fight injustice." film[ "poster"] = "https://images-na.ssl-images-amazon.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg" ''' res = requests.get('http://www.omdbapi.com/?t=' + movie + '&apikey=a345b6e2').text res = json.loads(res) try: film["poster"] = res['Poster'] film["plot"] = res['Plot'] film["imdb"] = res['Ratings'][0]['Value'] film["rotten"] = res['Ratings'][1]['Value'] film["metacritic"] = res['Ratings'][2]['Value'] except KeyError: continue except IndexError: film["imdb"] = '-' film["rotten"] = '-' film["metacritic"] = '-' ''' films.append(film) return {"movies": films}
def test_parser(self): json_input = os.path.join(os.path.dirname(__file__), 'files/input.json') with open(json_input) as input_file: torrents = json.load(input_file) json_output = os.path.join(os.path.dirname(__file__), 'files/output.json') with open(json_output) as output_file: expected_results = json.load(output_file) for torrent, expected_result in zip(torrents, expected_results): result = PTN.parse(torrent) self.assertEqual(result, expected_result)
def parse(): """ Endpoint for parsing a list of torrent names for scene information Receives a list of strings and returns objects containing the scene information For more information on the name parsing see https://github.com/divijbindlish/parse-torrent-name """ filenames = request.get_json() pretty_names = {filename:PTN.parse(filename) for filename in filenames} return jsonify(pretty_names)
def add_file(self, filepath): name = os.path.splitext(os.path.basename(filepath))[0] torrent = PTN.parse(name) file_id = hash_str(filepath) imdb_id = self.imdb.query(torrent['title'], year=torrent.get('year')) if imdb_id: media_id = hash_str(imdb_id) self.imdb.request_media(imdb_id) # prepare request if not media_id in self.medias: self.medias[media_id] = {'files': set(), 'imdb_id': imdb_id} if ('season' in torrent) and ('episode' in torrent): self.imdb.request_media_season(imdb_id, str(torrent['season'])) else: media_id = hash_str(torrent['title']) if not media_id in self.medias: self.medias[media_id] = { 'files': set(), 'seasons': dict() if 'season' in torrent else None, 'title': torrent['title'], 'year': torrent.get('year') } self.files[file_id] = { **self.get_file_metadata(filepath), 'episode_number': str(torrent['episode']) if 'episode' in torrent else None, 'filepath': filepath, 'media_id': media_id, 'quality': torrent.get('quality'), 'resolution': torrent.get('resolution'), 'season_number': str(torrent['season']) if 'season' in torrent else None, 'size': os.path.getsize(filepath) } media = self.medias[media_id] media['files'].add(file_id) LOG.info("Adding file '%s' (%s)", filepath, file_id) self.imdb.save_cache() self.publish()
def displayList(mode="display"): search_string=str(ui.lineEdit_5.text()).lower() movies=getMovieList() if mode=="search" and search_string=="": mode="display" global movieList ui.listView.clear() for movie in movies: movieInfo = ptn.parse(movie) movie=movieInfo["title"].title() movieList.append(movieInfo) itemString = QtCore.QString(movie) item = QtGui.QListWidgetItem(itemString) if mode=="search": if search_string in movieInfo["title"].lower(): ui.listView.addItem(item) else: ui.listView.addItem(item)
def handle_comic(comic_file): print 'Handling '+comic_file superdir = os.path.dirname(comic_file) name, ext = os.path.splitext(os.path.basename(comic_file)) comic_parse = PTN.parse(name) print comic_parse # The parser matches comic book title and issue number both into 'title' key. # Compile the regex that matches for comic issue numbers. issue_regex = re.compile('(\d{1,3}(\.\d*)*\s*$)') # Split the title by regex matching. title_split = issue_regex.split(comic_parse['title']) # Strip trailing spaces from the title. title = title_split[0].strip() # If the split found a match and actually split, make the second half the issue number. if len(title_split) >= 2: issue = ' ' + title_split[1].strip() else: issue = '' # A Free Comic Book Day issue has no issue number, so it replaces the issue number value. if 'fcbd' in comic_parse: if comic_parse['fcbd']: issue = ' FCBD' if 'year' in comic_parse: year = ' (' + str(comic_parse['year']) + ')' else: year = '' # Construct the renamed filename. rename = title + issue + year comic_file_renamed = os.path.join(superdir, rename + ext) print('Renaming', comic_file, '->', comic_file_renamed) c = comicvine_api.Comicvine() # comic_file_name = get_file_name(file_path) # print(urllib.request.urlopen('http://comicvine.gamespot.com/api/search/?format=json&api_key=' + comicvine_api_key + # '&query=dick+grayson&resource_type=character').read()) # print(pycomicvine.Series.description) # print(c[comic_file_name]) # comicvine.Volume.search(comic_file_name) sys.exit(0)
def test_parser(self): json_input = os.path.join(os.path.dirname(__file__), 'files/input.json') with open(json_input) as input_file: torrents = json.load(input_file) json_output = os.path.join(os.path.dirname(__file__), 'files/output.json') with open(json_output) as output_file: expected_results = json.load(output_file) self.assertEqual(len(torrents), len(expected_results)) for torrent, expected_result in zip(torrents, expected_results): print("Test: " + torrent) result = PTN.parse(torrent) for key in expected_result: if not expected_result[key]: self.assertNotIn(key, result) else: self.assertIn(key, result) result1 = result[key] if key == 'excess' and type(result1) == list: result1 = ', '.join(result1) self.assertEqual(result1, expected_result[key])
def handle_subtitle_file(subtitle_file): print('Handling subtitle file', subtitle_file) superdir = os.path.dirname(subtitle_file) name, ext = os.path.splitext(os.path.basename(subtitle_file)) subtitle_parse = PTN.parse(name) print(subtitle_parse)
def handle_video_file(video_file): print('Handling video file', video_file) superdir = os.path.dirname(video_file) name, ext = os.path.splitext(os.path.basename(video_file)) video_parse = PTN.parse(name) print(video_parse) if 'sample' not in video_parse: # Retrieve traits common to both movies and TV shows. title = str(video_parse['title']) # Get the year of release. if 'year' in video_parse: year = ' (' + str(video_parse['year']) + ')' else: year = '' # Get resolution if resolution was found. # Titles where resolution is 'HDTV' will not be found here. if 'resolution' in video_parse: resolution = ' [' + str(video_parse['resolution']) + ']' else: resolution = '' # Split to retrieve traits unique to TV shows. if is_television(video_parse): # Get season if season was found. if 'season' in video_parse: season = str(video_parse['season']) else: season = '0' # Get episode if episode was found. if 'episode' in video_parse: episode = str(video_parse['episode']) else: episode = '0' if len(season) > 1: if len(episode) > 1: rename = title + ' S'+season + 'E'+episode + year + resolution else: rename = title + ' S'+season + 'E0'+episode + year + resolution else: if len(episode) > 1: rename = title + ' S0'+season + 'E'+episode + year + resolution else: rename = title + ' S0'+season + 'E0'+episode + year + resolution else: # No unique traits to movies, simply rename with present traits. rename = title + year + resolution video_file_renamed = os.path.join(superdir, rename + ext) print('Renaming', video_file, '->', video_file_renamed) shutil.move(video_file, video_file_renamed) # Handle moving TV show file. if is_television(video_parse): # Get the folder for this TV show. telev_dir = os.path.join(dest_telev, title) # If the folder for this TV show doesn't exist, make it. if not os.path.exists(telev_dir): print('Creating directory', telev_dir) os.mkdir(telev_dir) # Get the folder for this season of this TV show. season_dir = os.path.join(telev_dir, 'Season ' + season) # If the folder for this season of this TV show doesn't exist yet, make it if not os.path.exists(season_dir): print('Creating directory', season_dir) os.mkdir(season_dir) # Move the TV show file into the folder of the season of the TV show. move_or_overwrite(video_file_renamed, season_dir, os.path.join(season_dir, rename + ext)) else: # Move the movie file into the movies folder. move_or_overwrite(video_file_renamed, dest_movie, os.path.join(dest_movie, rename + ext)) else: # If the parser found that this file is a sample file, skip it entirely. print('Sample video file, skipping.')
def getSeason(filename): #Return the season of a Show try: return PTN.parse(filename)['season'] except KeyError: return None
def get(self): self.response.headers['Content-type'] = 'application/json' self.response.out.write("> Initializing") osdb = opensubtitles.OpenSubtitles() osdb.login(username=OSORG_USERNAME, password=OSORG_PASSWORD) l = self.get_entity() logging.info(l.content) subreddit = r.get_subreddit('SubZorro') try: submissions = subreddit.get_new(limit=20) except praw.errors.HTTPException as h: self.response.out.write("> HTTP ERROR\n") # Comment Template ctitle = "" endmsg = """^This ^list ^of ^subtitles ^are ^taken ^from [^opensubtitles.org](http://www.opensubtitles.org) ^|""" shelp = " ^For ^feedback ^or ^suggestions ^contact [^/u/indigo6alpha](http://www.reddit.com/message/compose/?to=indigo6alpha)" endmsg = endmsg + shelp br = "\n\n---\n\n" for submission in submissions: visited = False summ = "" # Check all entities in the Datastore for this submission ID if(self.check_id(subid=submission.id)): try: _tag = re.search("""\[(Movie|MOVIE|movie|TV|tv|Tv)\]""", submission.title) l.content.append(submission.id) l.put() # Check if the submission has a movie or a tv tag if _tag is None or _tag.group(1).lower() not in ['movie','tv']: logging.info("No relevant tag found") continue comments_tree = submission.comments for comment in comments_tree: if str(comment.author) == 'SubZorro': visited = True if(visited == True): continue logging.info(submission.title) attrs = PTN.parse(re.sub("""\[(.*?)\]""","", submission.title).strip()) subs = {} try: if(attrs.has_key('season') and attrs.has_key('episode')): ctitle = "#####Subtitles for this episode: " subs = filterByName(osdb.searchTVWithQuery(name=attrs['title'],season=str(attrs['season']),episode=str(attrs['episode'])), attrs['title']) elif(attrs.has_key('year')): ctitle = "#####Subtitles for this movie: " subs = filterByName(osdb.searchMoviesWithQuery(name=attrs['title'], year=str(attrs['year'])), attrs['title']) else: self.response.out.write("> Skipping "+submission.id+"\n") continue except Exception as ex: logging.warning("Exception: "+str(ex)) continue if subs != [] and subs != None: try: for sub in subs: shash = hashlib.md5(sub['IDSubtitle']).hexdigest()[:8] summ += "> - **"+sub['MovieReleaseName'].strip()+"** - `"+sub['SubSumCD']+" CD` - [Download Subtitle](http://dl.opensubtitles.org/en/download/vrf-"+shash+"/sub/"+sub['IDSubtitle']+")\n\n" submission.add_comment(ctitle + br + summ.encode('ascii', 'ignore') + br + endmsg) self.response.out.write("> Posted subtitles for "+submission.id+"\n") continue except Exception as e: logging.warning("Subtitles Error: "+str(e)) continue else: self.response.out.write("> No subtitles found for: "+submission.id+"\n") continue except Exception as e: logging.warning("Submission Error: "+str(e)) continue self.response.write("> Done looping through submissions")