예제 #1
0
파일: jinja.py 프로젝트: opmuse/opmuse
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 ''
예제 #2
0
파일: library.py 프로젝트: opmuse/opmuse
    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}