def track_path(track, artist=None): track_structure = TrackStructureParser(track, data_override={'artist': artist}) path = track_structure.get_path() if path is not None: return path.decode('utf8', 'replace') else: return ''
def add(self, archive_password=None, audio_file=None, session=None, artist_name_fallback=None): cache_key = LibraryUpload.CACHE_KEY % (cherrypy.request.user.id, session) all_tracks = None if not cache.has(cache_key): raise cherrypy.HTTPError(status=409) else: all_tracks = cache.get(cache_key) if audio_file is not None and len(audio_file) == 0: audio_file = None if archive_password is not None and len(archive_password) == 0: archive_password = None content_disposition = cherrypy.request.headers.get('content-disposition') filename = content_disposition[content_disposition.index('filename=') + 9:] if filename.startswith('"') and filename.endswith('"'): filename = filename[1:-1] filename = unquote(filename) ext = os.path.splitext(filename)[1].lower()[1:] basename = os.path.splitext(filename)[0] cache_path = os.path.join(cherrypy.config['opmuse'].get('cache.path'), 'upload') if not os.path.exists(cache_path): os.mkdir(cache_path) tempdir = tempfile.mkdtemp(dir=cache_path) path = os.path.join(tempdir, filename) paths = [] rarfile.PATH_SEP = '/' messages = [] with open(path, 'wb') as fileobj: fileobj.write(cherrypy.request.rfile.read()) # this file is a regular file that belongs to an audio_file if audio_file is not None: track = None tries = 0 # try and sleep until we get the track.. this will almost always # be needed because of the async upload. while track is None and tries < 10: track = library_dao.get_track_by_filename(audio_file.encode('utf8')) tries += 1 if track is None: time.sleep(3) if track is None: messages.append(('warning', ("<strong>%s</strong>: Skipping <strong>%s</strong>, timeout trying to " + "find its track.") % (audio_file, filename))) else: track_structure = TrackStructureParser(track) track_path = track_structure.get_path(absolute=True) relative_track_path = track_structure.get_path(absolute=False).decode('utf8', 'replace') new_path = os.path.join(track_path, filename.encode('utf8')) if os.path.exists(new_path): messages.append(('warning', ("<strong>%s</strong>: Skipping <strong>%s</strong>, already exists " + "in <strong>%s</strong>.") % (audio_file, filename, relative_track_path))) else: shutil.move(path.encode('utf8'), new_path) messages.append(('info', ("<strong>%s</strong>: Uploaded <strong>%s</strong> to " + "<strong>%s</strong>.") % (audio_file, filename, relative_track_path))) elif ext == "zip": # set artist name fallback to zip's name so if it's missing artist tags # it's easily distinguishable and editable so it can be fixed after upload. artist_name_fallback = basename try: zip = ZipFile(path) if archive_password is not None: zip.setpassword(archive_password.encode()) zip.extractall(tempdir) os.remove(path) for name in zip.namelist(): namepath = os.path.join(tempdir, name) # ignore hidden files, e.g. OSX archive weirdness and such if name.startswith(".") or os.path.split(name)[0] == "__MACOSX": shutil.rmtree(namepath) continue paths.append(namepath.encode('utf8')) except Exception as error: messages.append(('danger', "<strong>%s</strong>: %s" % (os.path.basename(path), error))) elif ext == "rar": # look at corresponding ext == zip comment... artist_name_fallback = basename try: rar = RarFile(path) if archive_password is None and rar.needs_password(): messages.append(('danger', "<strong>%s</strong>: Needs password but none provided." % os.path.basename(path))) else: if archive_password is not None: rar.setpassword(archive_password) rar.extractall(tempdir) os.remove(path) for name in rar.namelist(): namepath = os.path.join(tempdir, name) if name.startswith("."): shutil.rmtree(namepath) continue paths.append(namepath.encode('utf8')) except Exception as error: messages.append(('danger', "<strong>%s</strong>: %s" % (os.path.basename(path), error))) # this is a plain audio file else: paths.append(path.encode('utf8')) for path in paths: # update modified time to now, we don't want the time from the zip # archive or whatever os.utime(path, None) if len(paths) > 0: tracks, add_files_messages = library_dao.add_files(paths, move=True, remove_dirs=False, artist_name_fallback=artist_name_fallback, user=cherrypy.request.user) messages += add_files_messages else: tracks = [] shutil.rmtree(tempdir) for track in tracks: all_tracks.append(track.id) if track.album is not None: remotes.update_album(track.album) if track.artist is not None: remotes.update_artist(track.artist) remotes.update_track(track) hierarchy = Library._produce_track_hierarchy(library_dao.get_tracks_by_ids(all_tracks)) return {'hierarchy': hierarchy, 'messages': messages}