From 8e68e69f930fa93dea6ecaa1df46d16d2c971e0a Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Tue, 24 Sep 2019 17:33:07 +0200
Subject: [PATCH] Added api endpoint, front-end code and plugin hook for
handling now playing track
---
api/funkwhale_api/history/serializers.py | 7 +++++++
api/funkwhale_api/history/signals.py | 4 ++++
api/funkwhale_api/history/views.py | 19 +++++++++++++++++--
api/tests/conftest.py | 6 ++++++
api/tests/history/test_views.py | 19 +++++++++++++++++++
front/src/components/audio/Player.vue | 14 +++++++++++++-
front/src/store/player.js | 8 ++++++++
7 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/api/funkwhale_api/history/serializers.py b/api/funkwhale_api/history/serializers.py
index c61fda6620..41b498291f 100644
--- a/api/funkwhale_api/history/serializers.py
+++ b/api/funkwhale_api/history/serializers.py
@@ -4,6 +4,7 @@ from funkwhale_api import plugins
from funkwhale_api.activity import serializers as activity_serializers
from funkwhale_api.common import utils
from funkwhale_api.federation import serializers as federation_serializers
+from funkwhale_api.music import models as music_models
from funkwhale_api.music.serializers import TrackActivitySerializer, TrackSerializer
from funkwhale_api.users.serializers import UserActivitySerializer, UserBasicSerializer
@@ -64,3 +65,9 @@ class ListeningWriteSerializer(serializers.ModelSerializer):
plugins_conf=plugins_conf,
)
return instance
+
+
+class NowSerializer(serializers.Serializer):
+ track = serializers.PrimaryKeyRelatedField(
+ queryset=music_models.Track.objects.all()
+ )
diff --git a/api/funkwhale_api/history/signals.py b/api/funkwhale_api/history/signals.py
index ad33d878c2..bdfbd225f5 100644
--- a/api/funkwhale_api/history/signals.py
+++ b/api/funkwhale_api/history/signals.py
@@ -4,3 +4,7 @@ from funkwhale_api import plugins
plugins.hooks.register(
plugins.Hook("history.listening.created", providing_args=["listening"])
)
+
+plugins.hooks.register(
+ plugins.Hook("history.listening.now", providing_args=["track", "user"])
+)
diff --git a/api/funkwhale_api/history/views.py b/api/funkwhale_api/history/views.py
index 6cdbc8a80f..97c1fe0aaf 100644
--- a/api/funkwhale_api/history/views.py
+++ b/api/funkwhale_api/history/views.py
@@ -1,9 +1,11 @@
-from rest_framework import mixins, viewsets
+from rest_framework import mixins, viewsets, response
+from rest_framework.decorators import action
from django.db.models import Prefetch
+from funkwhale_api import plugins
from funkwhale_api.activity import record
-from funkwhale_api.common import fields, permissions
+from funkwhale_api.common import fields, permissions, utils
from funkwhale_api.music.models import Track
from funkwhale_api.music import utils as music_utils
from . import filters, models, serializers
@@ -54,3 +56,16 @@ class ListeningViewSet(
context = super().get_serializer_context()
context["user"] = self.request.user
return context
+
+ @action(methods=["post"], detail=False)
+ def now(self, request, *args, **kwargs):
+ serializer = serializers.NowSerializer(data=request.data)
+ serializer.is_valid(raise_exception=True)
+ utils.on_commit(
+ plugins.hooks.dispatch,
+ "history.listening.now",
+ user=request.user,
+ track=serializer.validated_data["track"],
+ plugins_conf=request.plugins_conf,
+ )
+ return response.Response({}, status=204)
diff --git a/api/tests/conftest.py b/api/tests/conftest.py
index 82f05e9f39..98313c663b 100644
--- a/api/tests/conftest.py
+++ b/api/tests/conftest.py
@@ -437,3 +437,9 @@ def plugin_class():
def plugin(plugin_class):
return plugin_class("test", "test")
+
+
+@pytest.fixture
+def plugins_conf(mocker):
+ plugins_conf = mocker.patch("funkwhale_api.plugins.generate_plugins_conf")
+ return plugins_conf.return_value
diff --git a/api/tests/history/test_views.py b/api/tests/history/test_views.py
index 8ec9277103..675b18d9dd 100644
--- a/api/tests/history/test_views.py
+++ b/api/tests/history/test_views.py
@@ -2,6 +2,8 @@ import pytest
from django.urls import reverse
+from funkwhale_api import plugins
+
@pytest.mark.parametrize("level", ["instance", "me", "followers"])
def test_privacy_filter(preferences, level, factories, api_client):
@@ -11,3 +13,20 @@ def test_privacy_filter(preferences, level, factories, api_client):
response = api_client.get(url)
assert response.status_code == 200
assert response.data["count"] == 0
+
+
+def test_now(factories, logged_in_api_client, plugins_conf, mocker):
+ track = factories["music.Track"]()
+ url = reverse("api:v1:history:listenings-now")
+ on_commit = mocker.patch("funkwhale_api.common.utils.on_commit")
+ response = logged_in_api_client.post(url, {"track": track.pk})
+
+ on_commit.assert_called_once_with(
+ plugins.hooks.dispatch,
+ "history.listening.now",
+ track=track,
+ user=logged_in_api_client.user,
+ plugins_conf=plugins_conf,
+ )
+
+ assert response.status_code == 204
diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue
index 7fda9520f4..7349220eec 100644
--- a/front/src/components/audio/Player.vue
+++ b/front/src/components/audio/Player.vue
@@ -266,7 +266,8 @@ export default {
soundsCache: [],
soundId: null,
playTimeout: null,
- nextTrackPreloaded: false
+ nextTrackPreloaded: false,
+ nowPlayingTimeout: null,
}
},
mounted() {
@@ -408,6 +409,11 @@ export default {
})
},
onplay: function () {
+ if (trackData.id === self.currentTrack.id) {
+ self.nowPlayingTimeout = setTimeout(() => {
+ self.$store.dispatch('player/nowPlaying', trackData)
+ }, 5000)
+ }
self.$store.commit('player/isLoadingAudio', false)
self.$store.commit('player/resetErrorCount')
self.$store.commit('player/errored', false)
@@ -713,6 +719,9 @@ export default {
watch: {
currentTrack: {
async handler (newValue, oldValue) {
+ if (this.nowPlayingTimeout) {
+ clearTimeout(this.nowPlayingTimeout)
+ }
if (newValue === oldValue) {
return
}
@@ -746,6 +755,9 @@ export default {
if (newValue === true) {
this.soundId = this.currentSound.play(this.soundId)
} else {
+ if (this.nowPlayingTimeout) {
+ clearTimeout(this.nowPlayingTimeout)
+ }
this.currentSound.pause(this.soundId)
}
} else {
diff --git a/front/src/store/player.js b/front/src/store/player.js
index 6757f0beef..c02e7e45e6 100644
--- a/front/src/store/player.js
+++ b/front/src/store/player.js
@@ -126,6 +126,14 @@ export default {
logger.default.error('Could not record track in history')
})
},
+ nowPlaying ({commit, rootState}, trackData) {
+ if (!rootState.auth.authenticated) {
+ return
+ }
+ return axios.post('history/listenings/now/', {'track': trackData.id}).then((response) => {}, (response) => {
+ logger.default.error('Could not set track as now playing')
+ })
+ },
trackEnded ({dispatch, rootState}, track) {
dispatch('trackListened', track)
let queueState = rootState.queue
--
GitLab