Commit 98c7cb6f authored by Agate's avatar Agate 💬

Merge branch '260-subsonic-scrobble' into 'develop'

Resolve "Implement the scrobble API of subsonic"

Closes #260

See merge request funkwhale/funkwhale!221
parents 9ee0f09f 0f792bf7
......@@ -4,6 +4,7 @@ from django.db.models import functions, Count
from rest_framework import serializers
from funkwhale_api.history import models as history_models
from funkwhale_api.music import models as music_models
......@@ -228,3 +229,18 @@ def get_music_directory_data(artist):
td['size'] = tf.size
data['child'].append(td)
return data
class ScrobbleSerializer(serializers.Serializer):
submission = serializers.BooleanField(default=True, required=False)
id = serializers.PrimaryKeyRelatedField(
queryset=music_models.Track.objects.annotate(
files_count=Count('files')
).filter(files_count__gt=0)
)
def create(self, data):
return history_models.Listening.objects.create(
user=self.context['user'],
track=data['id'],
)
......@@ -519,7 +519,7 @@ class SubsonicViewSet(viewsets.GenericViewSet):
'message': 'cover art ID must be specified.'
}
})
if id.startswith('al-'):
try:
album_id = int(id.replace('al-', ''))
......@@ -551,4 +551,23 @@ class SubsonicViewSet(viewsets.GenericViewSet):
# let the proxy set the content-type
r = response.Response({}, content_type='')
r[file_header] = path
return r
\ No newline at end of file
return r
@list_route(
methods=['get', 'post'],
url_name='scrobble',
url_path='scrobble')
def scrobble(self, request, *args, **kwargs):
data = request.GET or request.POST
serializer = serializers.ScrobbleSerializer(
data=data, context={'user': request.user})
if not serializer.is_valid():
return response.Response({
'error': {
'code': 0,
'message': 'Invalid payload'
}
})
if serializer.validated_data['submission']:
serializer.save()
return response.Response({})
......@@ -214,3 +214,22 @@ def test_directory_serializer_artist(factories):
}
data = serializers.get_music_directory_data(artist)
assert data == expected
def test_scrobble_serializer(factories):
tf = factories['music.TrackFile']()
track = tf.track
user = factories['users.User']()
payload = {
'id': track.pk,
'submission': True,
}
serializer = serializers.ScrobbleSerializer(
data=payload, context={'user': user})
assert serializer.is_valid(raise_exception=True)
listening = serializer.save()
assert listening.user == user
assert listening.track == track
......@@ -404,3 +404,17 @@ def test_get_cover_art_album(factories, logged_in_api_client):
assert response['X-Accel-Redirect'] == music_views.get_file_path(
album.cover
).decode('utf-8')
def test_scrobble(factories, logged_in_api_client):
tf = factories['music.TrackFile']()
track = tf.track
url = reverse('api:subsonic-scrobble')
assert url.endswith('scrobble') is True
response = logged_in_api_client.get(
url, {'id': track.pk, 'submission': True})
assert response.status_code == 200
l = logged_in_api_client.user.listenings.latest('id')
assert l.track == track
Implemented scrobble endpoint of subsonic API, listenings are now tracked
correctly from third party apps that use this endpoint (#260)
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