def __init__(self, searchTerm, naked=False): self.__ClassName = "Beatport.ResultPage" self.__ReleaseList = [] # strip whitespaces on the edges searchTerm = searchTerm.strip() # replace white spaces searchTerm = searchTerm.replace(" ", "+") # remove ampersand from searchTerm searchTerm = searchTerm.replace("&", "") # # get the web data # ePrint(2, self.__ClassName, "Searching for term: " + searchTerm) if naked: return # maka request base = 'https://pro.beatport.com/search/releases?q={0}' base = base.format(searchTerm) r = requests.get(base) html = r.text self.__ReleaseList = self._get_releases(html, base)
def RenameQuery(self, dest): dest = path.join(path.dirname(self.Path), dest + "." + self.Type) ePrint(1, ":", "Rename: " + path.basename(self.Path) + " --> " + path.basename(dest), end=" ? ") choice = "k" while choice != "y" and choice != "n": choice = input("(y/n): ") if choice == "y": rename(self.Path, dest)
def Remeta(): # create an settings object and, which parses # arguemnts and sets default options ePrint(0, Remeta.__name__, "parsing arguments") settings = Settings(sys.argv[1:]) # create a main instance and run it main = Main(settings) main.Run()
def __init__(self, searchTerm): self.__ClassName = "Chemical.ResultPage" self.__ReleaseList = [] # set the base link for searching self.__BaseLink = r'http://www.chemical-records.co.uk/sc/search?SRI=true&inandout=true&ND=-1&Type=Music&must=' # strip whitespaces on the edges searchTerm = searchTerm.strip() # replace white spaces searchTerm = searchTerm.replace(" ", "+") # remove ampersand from searchTerm searchTerm = searchTerm.replace("&", "") # # get the web page source # ePrint(2, self.__ClassName, "Searching for term: " + searchTerm) response = urllib.request.urlopen(self.__BaseLink + searchTerm) # get page-source to str page = response.read() # return None if we have no source if len(page) == 0: return None # convert the string to a raw-string page = page.decode('Latin1') # # build the parser stream, we use minidom, after that parse the source # ePrint(2, self.__ClassName, "Parsing web source") p = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("dom")) dom_tree = p.parse(page) walker = treewalkers.getTreeWalker("dom") stream = walker(dom_tree) self.__CreateReleaseList__(stream)
def _get_releases(self, html, query_link): # see if we hav multiple pages soup = BeautifulSoup(html, "lxml") page_numbers = soup.find_all(True, class_='pagination-number') if len(page_numbers) == 0: return self._get_releases_paginated(html) else: releases = [] page_count = len(page_numbers) ePrint(1, self.__ClassName, "Found " + str(page_count) + " pages") for c in range(1, page_count + 1): r = requests.get(query_link + '&page=' + str(c)) html = r.text releases = releases + self._get_releases_paginated(html) return releases
def __init__(self, rel): # copy inherited object super().__init__() self.Name = rel.Name self.Catid = rel.Catid self.LabelName = rel.LabelName self.InfoPageLink = rel.InfoPageLink self.TrackList = deepcopy(rel.TrackList) # own members self.__ClassName = "ReleasePage" # # get the web page source # response = urllib.request.urlopen(self.InfoPageLink) # get page-source to str page = response.read() # return None if we have no source if len(page) == 0: return None # convert the string to a raw-string page = page.decode('Latin1') # # build the parser stream, we use minidom, after that parse the source # ePrint(2, self.__ClassName, "Parsing web source") p = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("dom")) dom_tree = p.parse(page) walker = treewalkers.getTreeWalker("dom") stream = walker(dom_tree) self.Parse(stream)
def __init__(self, searchTerm): self.__ClassName = "Beatport.ResultPage" self.__ReleaseList = [] # strip whitespaces on the edges searchTerm = searchTerm.strip() # replace white spaces searchTerm = searchTerm.replace(" ", "+") # remove ampersand from searchTerm searchTerm = searchTerm.replace("&", "") # # get the web data # ePrint(2, self.__ClassName, "Searching for term: " + searchTerm) # make a socket connection to the beatport api conn = http.client.HTTPConnection("api.beatport.com") conn.request("GET", "/catalog/3/search?query=" + searchTerm + "&facets[]=fieldType:release&perPage=500") r1 = conn.getresponse() #print(r1.status, r1.reason) mydict = json.loads(r1.read().decode()) # print(json.dumps(mydict["results"], sort_keys=True, indent=4)) #for entry in mydict["results"]: # print(entry["name"]) #print(len(mydict["results"])) # Check for nothing found if len(mydict["results"]) == 0: return None self.__CreateReleaseList__(mydict["results"])
def __init__(self, filePath): self.__ClassName = "File" # set default Type self.Type = "mp3" self.Path = filePath self.Basename = path.basename(filePath) t, b = self.GetSuffix() self.RelDir = "" self.RelDirIdx = 0 # set type if t: self.Type = t # set namebody, aka basename without extension self.NameBody = path.basename(b) # check if we find tag header and set the default if not self.TagHeader = None try: self.TagHeader = TagHeader(self.Path) except NoTagError: ePrint(1, self.__ClassName, "No Tag found in file: " + self.Basename)
def IdentifyTrack(self, term): sFktname = "search_track" # build search term. so connect artist and # title, delete some characters and split on # white spaces search_term_list = term.strip() search_term_list = search_term_list.replace("(","").replace(")","").lower() search_term_list = search_term_list.split() ePrint(2, sFktname, "looking for term: {}".format(search_term_list)) # to find the track, we constuct a ranking, with the term on the highest rank, wich # made the most hits max_hits = 0 match_list = [] for item in self.TrackList: item_hits = 0 # create target term search_target_list = item.Artist.lower() + " " + item.Title.lower() search_target_list = ReplaceChars("/_()-.:,", " ", search_target_list) search_target_list = search_target_list.split() ePrint(2, sFktname, "Matching against: "+ str(search_target_list)) # match for s in search_term_list: if s in search_target_list: item_hits += 1 # calculate a value wich is relative to the length of the search_term_list item_hits = item_hits / len(search_term_list) ePrint(2, sFktname, "Ranking points: " + str(item_hits)) # create a matchcount, item tupel match_list.append((item_hits, item)) if len(match_list) == 0: return None # sort matchlist match_list = sorted(match_list, key = lambda tup: tup[0], reverse = True) return match_list[0][1]
def Rename(self, dest): dest = path.join(path.dirname(self.Path), dest + "." + self.Type) ePrint(1, ":", "Renameing: " + path.basename(self.Path) + " --> " + path.basename(dest)) rename(self.Path, dest)
def __init__(self, arguments): self.__ClassName = "Settings" # # at first parse options # usage = "usage: %prog [options] filnames or searchpatterns" parser = OptionParser(usage = usage) parser.add_option("-c", "--copy", action = "store_true", help = "make a copy of original files before copying") parser.set_defaults(copy = False) parser.add_option("-w", "--cemelot", action = "store_true", help = "use Cemelot format for keys") parser.add_option("-a", "--ask", action = "store_true", help = "ask user if files are renamed") parser.add_option("-v", "--verb-level", action = "store", type= "int", dest = "verblevel", help = "specify a verbosity level") parser.add_option("-p", "--pattern", action = "store", type= "string", help = "specify a verbosity level") parser.add_option("-i", "--get-image", action = "store_true", dest = "getimage", help = "download release artwork if release search is invoked") parser.set_defaults(copy = False) parser.set_defaults(cemelot = False) parser.set_defaults(verblevel = 1) parser.set_defaults(pattern = "") parser.set_defaults(ask = False) parser.set_defaults(getimage = False) (options, args) = parser.parse_args(arguments) # # set options # # if a pattern was given initialize a Pattern object with # given string if options.pattern: self.Pattern = Pattern(options.pattern) else: self.Pattern = Pattern() # toggle copy mode on or of self.MakeCopy = options.copy # toggle use of crappy chemelot notation self.UseChemelot = options.cemelot # ask or not ask user self.Ask = options.ask # get image flag self.GetImage = options.getimage # set verbosity level # TODO: remove messi global variable self.VerbLevel = options.verblevel Helpers.G_VerbLevel = self.VerbLevel ePrint(2, self.__ClassName, "Pattern used: " + self.Pattern.Entry) ePrint(2, self.__ClassName, "Use copy mode: " + str(self.MakeCopy)) ePrint(2, self.__ClassName, "Use chemelot notation: " + str(self.UseChemelot)) # # create filelist and searchterm list # self.FileList = [] self.DirList = [] self.SearchTermList = [] for entry in args: if path.isdir(entry): self.DirList.append(entry) elif path.isfile(entry): # create a file object self.FileList.append(File(entry)) else: self.SearchTermList.append(entry) ePrint(3, self.__ClassName, "Search terms given:" + str(self.SearchTermList)) ePrint(3, self.__ClassName, "Files given:") for f in self.FileList: ePrint(3, self.__ClassName, str(f.GetDict()))
def Run(self): print() filled_tracks = [] unfilled_tracks = [] ## ## Handle Directories (Release Search) ## if self.Settings.HasDirs(): # here we only link the files to specific dirs # the next loop then cares about and first makes # a search in a release cache idx = 0 for folder in self.Settings.DirList: # # figure out the directory entries # file_list = os.listdir(folder) if not file_list: ePrint(1, self.__ClassName, "Skipping directory " + folder) continue ePrint(2, folder, "<-- Linking files") ePrint(2, "Containing: ", str(file_list) + "\n") # append them to the FileList for file_path in file_list: f = File(os.path.join(folder, file_path)) f.RelDir = folder f.RelDirIdx = idx #ePrint(2, "Fileending: ", str(file_list) + "\n") if f.Type in ["mp3", "flac", "wav", "wave", "ogg"]: self.Settings.FileList.append(f) idx += 1 ## ## Handle the FileList if existent ## if self.Settings.HasFiles(): track_list = [] for f in self.Settings.FileList: # # at first try to gather some data from the tags, so # create a track object # new_track = Track() # associate the track with its file and try to read # some info from the tags new_track.FileInstance = f new_track.FillFromFile() ePrint(1, ColorString(str(new_track.FileInstance.NameBody), "green"), "<-- Try to determine info") # if a track is fully filled continue with the next if (new_track.FilledEnough(self.Settings.Pattern)): ePrint(1, self.__ClassName, "Track is filled enough: " + str(new_track) + "\n") filled_tracks.append(new_track) continue # # Look in the cache # rel_page = None for t in filled_tracks: if new_track.FileInstance.RelDir != "" and \ new_track.FileInstance.RelDir == t.FileInstance.RelDir and \ t.Release: ePrint(2, self.__ClassName, "Using cache") rel_page = t.Release break if not rel_page: # # look at chemical if nothing is found in tags or cache # # first we check for an explicit searchterm idx = new_track.FileInstance.RelDirIdx if idx < len(self.Settings.SearchTermList): search_term = self.Settings.SearchTermList[idx] else: # if we have artist and filename availible set this as searchterm if new_track.Artist and new_track.Title: search_term = new_track.Artist + " " + new_track.Title else: # otherwise create search_term from filename search_term = new_track.FileInstance.NameBody ePrint(2, self.__ClassName, "Setting searchterm: " + search_term) # link it up on BeatportWeb res_page = BeatportWeb.ResultPage(search_term) # if we found nothing, we cut the searchterm if not res_page.GetReleaseList(): # at first remove signs symbols and retry search_term = ReplaceChars("/_()-.:,&?", " ", search_term) # strip "feat" terms p = re.compile(" feat ", re.IGNORECASE) search_term = p.sub("", search_term) res_page = BeatportWeb.ResultPage(search_term) if not res_page.GetReleaseList(): # second remove numbers search_term = ReplaceChars("0123456789", " ", search_term) res_page = BeatportWeb.ResultPage(search_term) # now strip words from the term if not res_page.GetReleaseList(): search_term_word_list = search_term.split() while len(search_term_word_list) > 1: search_term_word_list.pop() search_term = " ".join(search_term_word_list) res_page = BeatportWeb.ResultPage(search_term) if res_page.GetReleaseList(): break # if we finally found nothing, skip if not res_page.GetReleaseList(): ePrint(1, self.__ClassName, "Could not determine all fields for: " + new_track.FileInstance.Basename + "\n") unfilled_tracks.append(new_track) continue # # now we process the result list # release_list = res_page.GetReleaseList() # invoke the user if we have found more than one results if len(release_list) > 1: ePrint(1, self.__ClassName, "Multiple possilble releases found for: " + new_track.FileInstance.Basename + "Please type number. 0 to skip.") # TODO print sorted release_list = res_page.GetReleaseList() # sort the release list for better choosing release_list = sorted(release_list, key = lambda rel: str(rel), reverse = False) c = 1 for r in release_list: print("{:4d} : {!s:.150}".format(c, r)) c += 1 choice = -1 while choice < 0 or choice > len(release_list): choice = int(input(" <-- ")) if choice == 0: ePrint(1, self.__ClassName, "Skipping: " + new_track.FileInstance.Basename + "\n") unfilled_tracks.append(new_track) continue # choose result, pay attention on index release_candidate = release_list[choice - 1] else: release_candidate = release_list[0] # create a ReleasePage, from the release candidate . This determines all relevant # information for the release rel_page = BeatportWeb.ReleasePage(release_candidate) # # identify the track in the release # # create a search term if new_track.Artist and new_track.Title: search_term = new_track.Artist + " " + new_track.Title else: search_term = new_track.FileInstance.NameBody search_term = ReplaceChars("/_()-.:,", " ", search_term) cor_track = rel_page.IdentifyTrack(search_term) ePrint(1, self.__ClassName, "corresponding track: " + ColorString(str(cor_track), 'green')) # since we only have a corresponding track copy on demand if not new_track.Artist: new_track.Artist = cor_track.Artist if not new_track.Title: new_track.Title = cor_track.Title if not new_track.Key: new_track.Key = cor_track.Key if not new_track.Number: new_track.Number = cor_track.Number if new_track.FilledEnough(self.Settings.Pattern): ePrint(1, self.__ClassName, "Track is filled enough: " + str(new_track)) # link to the found release new_track.Release = rel_page filled_tracks.append(new_track) else: ePrint(1, self.__ClassName, "Could not determine all fields for: " + new_track.FileInstance.Basename) unfilled_tracks.append(new_track) print() # # Rename files # for track in filled_tracks: dest_name = self.Settings.Pattern.GetResolvedString(artist=track.Artist, title=track.Title, number=track.Number, key=track.Key) # function only needs the basename without extension if self.Settings.MakeCopy: #track.FileInstance.Copy(dest_name) pass else: if self.Settings.Ask == True: track.FileInstance.RenameQuery(dest_name) else: track.FileInstance.Rename(dest_name) # # handle dir renaming # handled_dirs = [] for track in filled_tracks: if track.FileInstance.RelDir and track.FileInstance.RelDir not in handled_dirs: #TODO remove code here # build a artist string, maximum 2 #artists = "" #c = 0 #for t in track.Release.TrackList: # artists += t.Artist + " " # if c >= 1: # break # c += 1 #print("Artist name: " + artists) # ## create destination string #artists = artists.strip() #artists = ReplaceChars(" ", ".", artists) #artists = artists.lower() rel_name = track.Release.Name.strip() rel_name = ReplaceChars("/'", "", rel_name) rel_name = ReplaceChars(" ", ".", rel_name) rel_name = rel_name.lower() dest = track.Release.Catid.lower() + ".-." + rel_name ePrint(2, self.__ClassName, track.FileInstance.RelDir) ePrint(2, self.__ClassName, dest) # download artwork if necessary if self.Settings.GetImage == True: image_path = os.path.join(track.FileInstance.RelDir, "artwork.jpg") if os.path.exists(image_path): ePrint(1, self.__ClassName, "Artwork already in release folder") else: ePrint(1, self.__ClassName, "Downloading Artwork") DownloadFile(track.Release.PictureLink, image_path) RenameDirQuery(track.FileInstance.RelDir, dest) handled_dirs.append(track.FileInstance.RelDir)
def __init__(self, settings): self.__ClassName = "Main" ePrint(2, self.__ClassName, "Entering") self.Settings = settings
def __init__(self, filePath): self.__ClassName = "TagHeader" ePrint(2, self.__ClassName, "Try to create stagger tag for: " + filePath) self.Tag = stagger.read_tag(filePath)