Removed acoustid support, as the integration was buggy and error-prone (#106)
This commit is contained in:
parent
28236ef7a7
commit
7b71463ef8
|
@ -9,7 +9,7 @@ from funkwhale_api.federation import models as federation_models
|
||||||
from funkwhale_api.federation import serializers as federation_serializers
|
from funkwhale_api.federation import serializers as federation_serializers
|
||||||
from funkwhale_api.taskapp import celery
|
from funkwhale_api.taskapp import celery
|
||||||
from funkwhale_api.providers.acoustid import get_acoustid_client
|
from funkwhale_api.providers.acoustid import get_acoustid_client
|
||||||
from funkwhale_api.providers.audiofile.tasks import import_track_data_from_path
|
from funkwhale_api.providers.audiofile import tasks as audiofile_tasks
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from . import models
|
from . import models
|
||||||
|
@ -73,13 +73,15 @@ def import_track_from_remote(library_track):
|
||||||
library_track.title, artist=artist, album=album)[0]
|
library_track.title, artist=artist, album=album)[0]
|
||||||
|
|
||||||
|
|
||||||
def _do_import(import_job, replace=False, use_acoustid=True):
|
def _do_import(import_job, replace=False, use_acoustid=False):
|
||||||
from_file = bool(import_job.audio_file)
|
from_file = bool(import_job.audio_file)
|
||||||
mbid = import_job.mbid
|
mbid = import_job.mbid
|
||||||
acoustid_track_id = None
|
acoustid_track_id = None
|
||||||
duration = None
|
duration = None
|
||||||
track = None
|
track = None
|
||||||
use_acoustid = use_acoustid and preferences.get('providers_acoustid__api_key')
|
# use_acoustid = use_acoustid and preferences.get('providers_acoustid__api_key')
|
||||||
|
# Acoustid is not reliable, we disable it for now.
|
||||||
|
use_acoustid = False
|
||||||
if not mbid and use_acoustid and from_file:
|
if not mbid and use_acoustid and from_file:
|
||||||
# we try to deduce mbid from acoustid
|
# we try to deduce mbid from acoustid
|
||||||
client = get_acoustid_client()
|
client = get_acoustid_client()
|
||||||
|
@ -91,11 +93,12 @@ def _do_import(import_job, replace=False, use_acoustid=True):
|
||||||
if mbid:
|
if mbid:
|
||||||
track, _ = models.Track.get_or_create_from_api(mbid=mbid)
|
track, _ = models.Track.get_or_create_from_api(mbid=mbid)
|
||||||
elif import_job.audio_file:
|
elif import_job.audio_file:
|
||||||
track = import_track_data_from_path(import_job.audio_file.path)
|
track = audiofile_tasks.import_track_data_from_path(
|
||||||
|
import_job.audio_file.path)
|
||||||
elif import_job.library_track:
|
elif import_job.library_track:
|
||||||
track = import_track_from_remote(import_job.library_track)
|
track = import_track_from_remote(import_job.library_track)
|
||||||
elif import_job.source.startswith('file://'):
|
elif import_job.source.startswith('file://'):
|
||||||
track = import_track_data_from_path(
|
track = audiofile_tasks.import_track_data_from_path(
|
||||||
import_job.source.replace('file://', '', 1))
|
import_job.source.replace('file://', '', 1))
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -151,7 +154,7 @@ def _do_import(import_job, replace=False, use_acoustid=True):
|
||||||
models.ImportJob.objects.filter(
|
models.ImportJob.objects.filter(
|
||||||
status__in=['pending', 'errored']),
|
status__in=['pending', 'errored']),
|
||||||
'import_job')
|
'import_job')
|
||||||
def import_job_run(self, import_job, replace=False, use_acoustid=True):
|
def import_job_run(self, import_job, replace=False, use_acoustid=False):
|
||||||
def mark_errored():
|
def mark_errored():
|
||||||
import_job.status = 'errored'
|
import_job.status = 'errored'
|
||||||
import_job.save(update_fields=['status'])
|
import_job.save(update_fields=['status'])
|
||||||
|
|
|
@ -54,13 +54,6 @@ class Command(BaseCommand):
|
||||||
'import and not much disk space available.'
|
'import and not much disk space available.'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
|
||||||
'--no-acoustid',
|
|
||||||
action='store_true',
|
|
||||||
dest='no_acoustid',
|
|
||||||
default=False,
|
|
||||||
help='Use this flag to completely bypass acoustid completely',
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--noinput', '--no-input', action='store_false', dest='interactive',
|
'--noinput', '--no-input', action='store_false', dest='interactive',
|
||||||
help="Do NOT prompt the user for input of any kind.",
|
help="Do NOT prompt the user for input of any kind.",
|
||||||
|
@ -118,7 +111,6 @@ class Command(BaseCommand):
|
||||||
len(filtered['new'])))
|
len(filtered['new'])))
|
||||||
|
|
||||||
self.stdout.write('Selected options: {}'.format(', '.join([
|
self.stdout.write('Selected options: {}'.format(', '.join([
|
||||||
'no acoustid' if options['no_acoustid'] else 'use acoustid',
|
|
||||||
'in place' if options['in_place'] else 'copy music files',
|
'in place' if options['in_place'] else 'copy music files',
|
||||||
])))
|
])))
|
||||||
if len(filtered['new']) == 0:
|
if len(filtered['new']) == 0:
|
||||||
|
@ -201,4 +193,4 @@ class Command(BaseCommand):
|
||||||
job.save()
|
job.save()
|
||||||
import_handler(
|
import_handler(
|
||||||
import_job_id=job.pk,
|
import_job_id=job.pk,
|
||||||
use_acoustid=not options['no_acoustid'])
|
use_acoustid=False)
|
||||||
|
|
|
@ -105,7 +105,7 @@ def test_run_import_skipping_accoustid(factories, mocker):
|
||||||
def test__do_import_skipping_accoustid(factories, mocker):
|
def test__do_import_skipping_accoustid(factories, mocker):
|
||||||
t = factories['music.Track']()
|
t = factories['music.Track']()
|
||||||
m = mocker.patch(
|
m = mocker.patch(
|
||||||
'funkwhale_api.music.tasks.import_track_data_from_path',
|
'funkwhale_api.providers.audiofile.tasks.import_track_data_from_path',
|
||||||
return_value=t)
|
return_value=t)
|
||||||
path = os.path.join(DATA_DIR, 'test.ogg')
|
path = os.path.join(DATA_DIR, 'test.ogg')
|
||||||
job = factories['music.FileImportJob'](
|
job = factories['music.FileImportJob'](
|
||||||
|
@ -121,7 +121,7 @@ def test__do_import_skipping_accoustid_if_no_key(
|
||||||
preferences['providers_acoustid__api_key'] = ''
|
preferences['providers_acoustid__api_key'] = ''
|
||||||
t = factories['music.Track']()
|
t = factories['music.Track']()
|
||||||
m = mocker.patch(
|
m = mocker.patch(
|
||||||
'funkwhale_api.music.tasks.import_track_data_from_path',
|
'funkwhale_api.providers.audiofile.tasks.import_track_data_from_path',
|
||||||
return_value=t)
|
return_value=t)
|
||||||
path = os.path.join(DATA_DIR, 'test.ogg')
|
path = os.path.join(DATA_DIR, 'test.ogg')
|
||||||
job = factories['music.FileImportJob'](
|
job = factories['music.FileImportJob'](
|
||||||
|
@ -132,32 +132,14 @@ def test__do_import_skipping_accoustid_if_no_key(
|
||||||
m.assert_called_once_with(p)
|
m.assert_called_once_with(p)
|
||||||
|
|
||||||
|
|
||||||
def test_import_job_can_be_skipped(
|
def test_import_job_skip_if_already_exists(
|
||||||
artists, albums, tracks, factories, mocker, preferences):
|
artists, albums, tracks, factories, mocker):
|
||||||
preferences['providers_acoustid__api_key'] = 'test'
|
|
||||||
path = os.path.join(DATA_DIR, 'test.ogg')
|
path = os.path.join(DATA_DIR, 'test.ogg')
|
||||||
mbid = '9968a9d6-8d92-4051-8f76-674e157b6eed'
|
mbid = '9968a9d6-8d92-4051-8f76-674e157b6eed'
|
||||||
track_file = factories['music.TrackFile'](track__mbid=mbid)
|
track_file = factories['music.TrackFile'](track__mbid=mbid)
|
||||||
acoustid_payload = {
|
|
||||||
'results': [
|
|
||||||
{'id': 'e475bf79-c1ce-4441-bed7-1e33f226c0a2',
|
|
||||||
'recordings': [
|
|
||||||
{
|
|
||||||
'duration': 268,
|
|
||||||
'id': mbid}],
|
|
||||||
'score': 0.860825}],
|
|
||||||
'status': 'ok'
|
|
||||||
}
|
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
'funkwhale_api.musicbrainz.api.artists.get',
|
'funkwhale_api.providers.audiofile.tasks.import_track_data_from_path',
|
||||||
return_value=artists['get']['adhesive_wombat'])
|
return_value=track_file.track)
|
||||||
mocker.patch(
|
|
||||||
'funkwhale_api.musicbrainz.api.releases.get',
|
|
||||||
return_value=albums['get']['marsupial'])
|
|
||||||
mocker.patch(
|
|
||||||
'funkwhale_api.musicbrainz.api.recordings.search',
|
|
||||||
return_value=tracks['search']['8bitadventures'])
|
|
||||||
mocker.patch('acoustid.match', return_value=acoustid_payload)
|
|
||||||
|
|
||||||
job = factories['music.FileImportJob'](audio_file__path=path)
|
job = factories['music.FileImportJob'](audio_file__path=path)
|
||||||
f = job.audio_file
|
f = job.audio_file
|
||||||
|
@ -171,29 +153,23 @@ def test_import_job_can_be_skipped(
|
||||||
|
|
||||||
|
|
||||||
def test_import_job_can_be_errored(factories, mocker, preferences):
|
def test_import_job_can_be_errored(factories, mocker, preferences):
|
||||||
preferences['providers_acoustid__api_key'] = 'test'
|
|
||||||
path = os.path.join(DATA_DIR, 'test.ogg')
|
path = os.path.join(DATA_DIR, 'test.ogg')
|
||||||
mbid = '9968a9d6-8d92-4051-8f76-674e157b6eed'
|
mbid = '9968a9d6-8d92-4051-8f76-674e157b6eed'
|
||||||
track_file = factories['music.TrackFile'](track__mbid=mbid)
|
track_file = factories['music.TrackFile'](track__mbid=mbid)
|
||||||
acoustid_payload = {
|
|
||||||
'results': [
|
|
||||||
{'id': 'e475bf79-c1ce-4441-bed7-1e33f226c0a2',
|
|
||||||
'recordings': [
|
|
||||||
{
|
|
||||||
'duration': 268,
|
|
||||||
'id': mbid}],
|
|
||||||
'score': 0.860825}],
|
|
||||||
'status': 'ok'
|
|
||||||
}
|
|
||||||
class MyException(Exception):
|
class MyException(Exception):
|
||||||
pass
|
pass
|
||||||
mocker.patch('acoustid.match', side_effect=MyException())
|
|
||||||
|
mocker.patch(
|
||||||
|
'funkwhale_api.music.tasks._do_import',
|
||||||
|
side_effect=MyException())
|
||||||
|
|
||||||
job = factories['music.FileImportJob'](
|
job = factories['music.FileImportJob'](
|
||||||
audio_file__path=path, track_file=None)
|
audio_file__path=path, track_file=None)
|
||||||
|
|
||||||
with pytest.raises(MyException):
|
with pytest.raises(MyException):
|
||||||
tasks.import_job_run(import_job_id=job.pk)
|
tasks.import_job_run(import_job_id=job.pk)
|
||||||
|
|
||||||
job.refresh_from_db()
|
job.refresh_from_db()
|
||||||
|
|
||||||
assert job.track_file is None
|
assert job.track_file is None
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import pytest
|
import pytest
|
||||||
import acoustid
|
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
@ -17,8 +16,6 @@ DATA_DIR = os.path.join(
|
||||||
|
|
||||||
|
|
||||||
def test_can_create_track_from_file_metadata(db, mocker):
|
def test_can_create_track_from_file_metadata(db, mocker):
|
||||||
mocker.patch(
|
|
||||||
'acoustid.match', side_effect=acoustid.WebServiceError('test'))
|
|
||||||
metadata = {
|
metadata = {
|
||||||
'artist': ['Test artist'],
|
'artist': ['Test artist'],
|
||||||
'album': ['Test album'],
|
'album': ['Test album'],
|
||||||
|
@ -94,24 +91,6 @@ def test_import_files_creates_a_batch_and_job(factories, mocker):
|
||||||
assert job.audio_file.read() == f.read()
|
assert job.audio_file.read() == f.read()
|
||||||
|
|
||||||
assert job.source == 'file://' + path
|
assert job.source == 'file://' + path
|
||||||
m.assert_called_once_with(
|
|
||||||
import_job_id=job.pk,
|
|
||||||
use_acoustid=True)
|
|
||||||
|
|
||||||
|
|
||||||
def test_import_files_skip_acoustid(factories, mocker):
|
|
||||||
m = mocker.patch('funkwhale_api.music.tasks.import_job_run')
|
|
||||||
user = factories['users.User'](username='me')
|
|
||||||
path = os.path.join(DATA_DIR, 'dummy_file.ogg')
|
|
||||||
call_command(
|
|
||||||
'import_files',
|
|
||||||
path,
|
|
||||||
username='me',
|
|
||||||
async=False,
|
|
||||||
no_acoustid=True,
|
|
||||||
interactive=False)
|
|
||||||
batch = user.imports.latest('id')
|
|
||||||
job = batch.jobs.first()
|
|
||||||
m.assert_called_once_with(
|
m.assert_called_once_with(
|
||||||
import_job_id=job.pk,
|
import_job_id=job.pk,
|
||||||
use_acoustid=False)
|
use_acoustid=False)
|
||||||
|
@ -128,7 +107,6 @@ def test_import_files_skip_if_path_already_imported(factories, mocker):
|
||||||
path,
|
path,
|
||||||
username='me',
|
username='me',
|
||||||
async=False,
|
async=False,
|
||||||
no_acoustid=True,
|
|
||||||
interactive=False)
|
interactive=False)
|
||||||
assert user.imports.count() == 0
|
assert user.imports.count() == 0
|
||||||
|
|
||||||
|
@ -142,7 +120,6 @@ def test_import_files_works_with_utf8_file_name(factories, mocker):
|
||||||
path,
|
path,
|
||||||
username='me',
|
username='me',
|
||||||
async=False,
|
async=False,
|
||||||
no_acoustid=True,
|
|
||||||
interactive=False)
|
interactive=False)
|
||||||
batch = user.imports.latest('id')
|
batch = user.imports.latest('id')
|
||||||
job = batch.jobs.first()
|
job = batch.jobs.first()
|
||||||
|
@ -162,7 +139,6 @@ def test_import_files_in_place(factories, mocker, settings):
|
||||||
username='me',
|
username='me',
|
||||||
async=False,
|
async=False,
|
||||||
in_place=True,
|
in_place=True,
|
||||||
no_acoustid=True,
|
|
||||||
interactive=False)
|
interactive=False)
|
||||||
batch = user.imports.latest('id')
|
batch = user.imports.latest('id')
|
||||||
job = batch.jobs.first()
|
job = batch.jobs.first()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Removed acoustid support, as the integration was buggy and error-prone (#106)
|
|
@ -6,7 +6,8 @@ From music directory on the server
|
||||||
|
|
||||||
You can import music files in funkwhale assuming they are located on the server
|
You can import music files in funkwhale assuming they are located on the server
|
||||||
and readable by the funkwhale application. Your music files should contain at
|
and readable by the funkwhale application. Your music files should contain at
|
||||||
least an ``artist``, ``album`` and ``title`` tags.
|
least an ``artist``, ``album`` and ``title`` tags, but we recommend you tag
|
||||||
|
it extensively using a proper tool, such as Beets or Musicbrainz Picard.
|
||||||
|
|
||||||
You can import those tracks as follows, assuming they are located in
|
You can import those tracks as follows, assuming they are located in
|
||||||
``/srv/funkwhale/data/music``:
|
``/srv/funkwhale/data/music``:
|
||||||
|
@ -32,11 +33,6 @@ get details::
|
||||||
For the best results, we recommand tagging your music collection through
|
For the best results, we recommand tagging your music collection through
|
||||||
`Picard <http://picard.musicbrainz.org/>`_ in order to have the best quality metadata.
|
`Picard <http://picard.musicbrainz.org/>`_ in order to have the best quality metadata.
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Autotagging using acoustid is experimental now and can yield unexpected
|
|
||||||
result. You can disable acoustid by passing the --no-acoustid flag.
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
This command is idempotent, meaning you can run it multiple times on the same
|
This command is idempotent, meaning you can run it multiple times on the same
|
||||||
|
@ -44,7 +40,7 @@ get details::
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
At the moment, only OGG/Vorbis and MP3 files with ID3 tags are supported
|
At the moment, only Flac, OGG/Vorbis and MP3 files with ID3 tags are supported
|
||||||
|
|
||||||
|
|
||||||
.. _in-place-import:
|
.. _in-place-import:
|
||||||
|
|
|
@ -93,8 +93,7 @@ export default {
|
||||||
label: this.$t('Imports'),
|
label: this.$t('Imports'),
|
||||||
id: 'imports',
|
id: 'imports',
|
||||||
settings: [
|
settings: [
|
||||||
'providers_youtube__api_key',
|
'providers_youtube__api_key'
|
||||||
'providers_acoustid__api_key'
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue