API Endpoint to list lirary tracks
This commit is contained in:
parent
bdf9347917
commit
57bf43bb96
|
@ -7,5 +7,9 @@ router.register(
|
|||
r'libraries',
|
||||
views.LibraryViewSet,
|
||||
'libraries')
|
||||
router.register(
|
||||
r'library-tracks',
|
||||
views.LibraryTrackViewSet,
|
||||
'library-tracks')
|
||||
|
||||
urlpatterns = router.urls
|
||||
|
|
|
@ -17,6 +17,20 @@ class LibraryFilter(django_filters.FilterSet):
|
|||
}
|
||||
|
||||
|
||||
class LibraryTrackFilter(django_filters.FilterSet):
|
||||
library = django_filters.CharFilter('library__uuid')
|
||||
|
||||
class Meta:
|
||||
model = models.LibraryTrack
|
||||
fields = {
|
||||
'library': ['exact'],
|
||||
'artist_name': ['exact', 'icontains'],
|
||||
'title': ['exact', 'icontains'],
|
||||
'album_title': ['exact', 'icontains'],
|
||||
'audio_mimetype': ['exact', 'icontains'],
|
||||
}
|
||||
|
||||
|
||||
class FollowFilter(django_filters.FilterSet):
|
||||
ordering = django_filters.OrderingFilter(
|
||||
# tuple-mapping retains order
|
||||
|
|
|
@ -253,6 +253,29 @@ class APILibraryCreateSerializer(serializers.ModelSerializer):
|
|||
return library
|
||||
|
||||
|
||||
class APILibraryTrackSerializer(serializers.ModelSerializer):
|
||||
library = APILibrarySerializer()
|
||||
|
||||
class Meta:
|
||||
model = models.LibraryTrack
|
||||
fields = [
|
||||
'id',
|
||||
'url',
|
||||
'audio_url',
|
||||
'audio_mimetype',
|
||||
'creation_date',
|
||||
'modification_date',
|
||||
'fetched_date',
|
||||
'published_date',
|
||||
'metadata',
|
||||
'artist_name',
|
||||
'album_title',
|
||||
'title',
|
||||
'library',
|
||||
'local_track_file',
|
||||
]
|
||||
|
||||
|
||||
class FollowSerializer(serializers.Serializer):
|
||||
id = serializers.URLField()
|
||||
object = serializers.URLField()
|
||||
|
|
|
@ -2,6 +2,7 @@ import json
|
|||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
|
@ -58,6 +59,9 @@ def scan_library(library, until=None):
|
|||
data = lb.get_library_data(library.url)
|
||||
scan_library_page.delay(
|
||||
library_id=library.id, page_url=data['first'], until=until)
|
||||
library.fetched_date = timezone.now()
|
||||
library.tracks_count = data['totalItems']
|
||||
library.save(update_fields=['fetched_date', 'tracks_count'])
|
||||
|
||||
|
||||
@celery.app.task(
|
||||
|
|
|
@ -14,6 +14,7 @@ from rest_framework.decorators import list_route, detail_route
|
|||
from rest_framework.serializers import ValidationError
|
||||
|
||||
from funkwhale_api.common import utils as funkwhale_utils
|
||||
from funkwhale_api.common.permissions import HasModelPermission
|
||||
from funkwhale_api.music.models import TrackFile
|
||||
|
||||
from . import activity
|
||||
|
@ -166,12 +167,16 @@ class MusicFilesViewSet(FederationMixin, viewsets.GenericViewSet):
|
|||
return response.Response(data)
|
||||
|
||||
|
||||
class LibraryPermission(HasModelPermission):
|
||||
model = models.Library
|
||||
|
||||
|
||||
class LibraryViewSet(
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
mixins.ListModelMixin,
|
||||
viewsets.GenericViewSet):
|
||||
permission_classes = [rest_permissions.DjangoModelPermissions]
|
||||
permission_classes = [LibraryPermission]
|
||||
queryset = models.Library.objects.all().select_related(
|
||||
'actor',
|
||||
'follow',
|
||||
|
@ -184,6 +189,7 @@ class LibraryViewSet(
|
|||
'creation_date',
|
||||
'fetched_date',
|
||||
'actor__domain',
|
||||
'tracks_count',
|
||||
)
|
||||
|
||||
@list_route(methods=['get'])
|
||||
|
@ -203,11 +209,11 @@ class LibraryViewSet(
|
|||
data=request.data
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
id = tasks.scan_library.delay(
|
||||
result = tasks.scan_library.delay(
|
||||
library_id=library.pk,
|
||||
until=serializer.validated_data['until']
|
||||
until=serializer.validated_data.get('until')
|
||||
)
|
||||
return response.Response({'task': id})
|
||||
return response.Response({'task': result.id})
|
||||
|
||||
@list_route(methods=['get'])
|
||||
def following(self, request, *args, **kwargs):
|
||||
|
@ -249,3 +255,26 @@ class LibraryViewSet(
|
|||
serializer.is_valid(raise_exception=True)
|
||||
library = serializer.save()
|
||||
return response.Response(serializer.data, status=201)
|
||||
|
||||
|
||||
class LibraryTrackViewSet(
|
||||
mixins.ListModelMixin,
|
||||
viewsets.GenericViewSet):
|
||||
permission_classes = [LibraryPermission]
|
||||
queryset = models.LibraryTrack.objects.all().select_related(
|
||||
'library__actor',
|
||||
'library__follow',
|
||||
'local_track_file',
|
||||
)
|
||||
filter_class = filters.LibraryTrackFilter
|
||||
serializer_class = serializers.APILibraryTrackSerializer
|
||||
ordering_fields = (
|
||||
'id',
|
||||
'artist_name',
|
||||
'title',
|
||||
'album_title',
|
||||
'creation_date',
|
||||
'modification_date',
|
||||
'fetched_date',
|
||||
'published_date',
|
||||
)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.core.paginator import Paginator
|
||||
from django.utils import timezone
|
||||
|
||||
from funkwhale_api.federation import serializers
|
||||
from funkwhale_api.federation import tasks
|
||||
|
@ -21,6 +22,7 @@ def test_scan_library_page_does_nothing_if_federation_disabled(
|
|||
|
||||
def test_scan_library_fetches_page_and_calls_scan_page(
|
||||
mocker, factories, r_mock):
|
||||
now = timezone.now()
|
||||
library = factories['federation.Library'](federation_enabled=True)
|
||||
collection_conf = {
|
||||
'actor': library.actor,
|
||||
|
@ -39,6 +41,8 @@ def test_scan_library_fetches_page_and_calls_scan_page(
|
|||
page_url=collection.data['first'],
|
||||
until=None,
|
||||
)
|
||||
library.refresh_from_db()
|
||||
assert library.fetched_date > now
|
||||
|
||||
|
||||
def test_scan_page_fetches_page_and_creates_tracks(
|
||||
|
|
|
@ -312,7 +312,7 @@ def test_can_patch_library(factories, superuser_api_client):
|
|||
def test_scan_library(factories, mocker, superuser_api_client):
|
||||
scan = mocker.patch(
|
||||
'funkwhale_api.federation.tasks.scan_library.delay',
|
||||
return_value='id')
|
||||
return_value=mocker.Mock(id='id'))
|
||||
library = factories['federation.Library']()
|
||||
now = timezone.now()
|
||||
data = {
|
||||
|
@ -329,3 +329,20 @@ def test_scan_library(factories, mocker, superuser_api_client):
|
|||
library_id=library.pk,
|
||||
until=now
|
||||
)
|
||||
|
||||
|
||||
def test_list_library_tracks(factories, superuser_api_client):
|
||||
library = factories['federation.Library']()
|
||||
lts = list(reversed(factories['federation.LibraryTrack'].create_batch(
|
||||
size=5, library=library)))
|
||||
factories['federation.LibraryTrack'].create_batch(size=5)
|
||||
url = reverse('api:v1:federation:library-tracks-list')
|
||||
response = superuser_api_client.get(url, {'library': library.uuid})
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.data == {
|
||||
'results': serializers.APILibraryTrackSerializer(lts, many=True).data,
|
||||
'count': 5,
|
||||
'previous': None,
|
||||
'next': None,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue