Verified Commit 57bf43bb authored by Eliot Berriot's avatar Eliot Berriot
Browse files

API Endpoint to list lirary tracks

parent bdf93479
......@@ -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',
)
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,
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment