diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index 18f181e884aec2877c07f3b6dac533411d653e94..98fc1965b51dff90a9aaae1717e5dc7ca5032538 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -463,6 +463,26 @@ class TrackFile(models.Model): self.mimetype = utils.guess_mimetype(self.audio_file) return super().save(**kwargs) + @property + def serve_from_source_path(self): + if not self.source or not self.source.startswith('file://'): + raise ValueError('Cannot serve this file from source') + serve_path = settings.MUSIC_DIRECTORY_SERVE_PATH + prefix = settings.MUSIC_DIRECTORY_PATH + if not serve_path or not prefix: + raise ValueError( + 'You need to specify MUSIC_DIRECTORY_SERVE_PATH and ' + 'MUSIC_DIRECTORY_PATH to serve in-place imported files' + ) + file_path = self.source.replace('file://', '', 1) + parts = os.path.split(file_path.replace(prefix, '', 1)) + if parts[0] == '/': + parts = parts[1:] + return os.path.join( + serve_path, + *parts + ) + IMPORT_STATUS_CHOICES = ( ('pending', 'Pending'), diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index f961e3fdff340b24d596310ab62609f79f10a7b9..d03b55e50fb16506102e43d2429fbae9b9fc172b 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -224,12 +224,21 @@ class TrackFileViewSet(viewsets.ReadOnlyModelViewSet): library_track = qs.get(pk=library_track.pk) library_track.download_audio() audio_file = library_track.audio_file + file_path = '{}{}'.format( + settings.PROTECT_FILES_PATH, + audio_file.url) mt = library_track.audio_mimetype + elif audio_file: + file_path = '{}{}'.format( + settings.PROTECT_FILES_PATH, + audio_file.url) + elif f.source and f.source.startswith('file://'): + file_path = '{}{}'.format( + settings.PROTECT_FILES_PATH + '/music', + f.serve_from_source_path) response = Response() filename = f.filename - response['X-Accel-Redirect'] = "{}{}".format( - settings.PROTECT_FILES_PATH, - audio_file.url) + response['X-Accel-Redirect'] = file_path filename = "filename*=UTF-8''{}".format( urllib.parse.quote(filename)) response["Content-Disposition"] = "attachment; {}".format(filename) diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py index 81f34fbe9d95d41e198ef783746df65dcdbb0561..95c56d914893fb775a2325515b06662f19a32859 100644 --- a/api/tests/music/test_views.py +++ b/api/tests/music/test_views.py @@ -93,6 +93,25 @@ def test_can_proxy_remote_track( assert library_track.audio_file.read() == b'test' +def test_can_serve_in_place_imported_file( + factories, settings, api_client, r_mock): + settings.PROTECT_AUDIO_FILES = False + settings.MUSIC_DIRECTORY_SERVE_PATH = '/host/music' + settings.MUSIC_DIRECTORY_PATH = '/music' + settings.MUSIC_DIRECTORY_PATH = '/music' + track_file = factories['music.TrackFile']( + in_place=True, + source='file:///music/test.ogg') + + response = api_client.get(track_file.path) + + assert response.status_code == 200 + assert response['X-Accel-Redirect'] == '{}{}'.format( + settings.PROTECT_FILES_PATH, + '/music/host/music/test.ogg' + ) + + def test_can_create_import_from_federation_tracks( factories, superuser_api_client, mocker): lts = factories['federation.LibraryTrack'].create_batch(size=5)