From 7ae0b23c15f5869499f2e799f5dcf83b2e780b14 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Wed, 15 Jan 2020 14:39:50 +0100 Subject: [PATCH] See #170: filtering subscribed channels in API --- api/funkwhale_api/audio/filters.py | 22 +++++++++++++++++++- api/tests/audio/test_filters.py | 32 ++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 api/tests/audio/test_filters.py diff --git a/api/funkwhale_api/audio/filters.py b/api/funkwhale_api/audio/filters.py index 02776e032..9a8bec6cd 100644 --- a/api/funkwhale_api/audio/filters.py +++ b/api/funkwhale_api/audio/filters.py @@ -1,3 +1,5 @@ +from django.db.models import Q + import django_filters from funkwhale_api.common import fields @@ -23,12 +25,30 @@ class ChannelFilter(moderation_filters.HiddenContentFilterSet): ) tag = TAG_FILTER scope = common_filters.ActorScopeFilter(actor_field="attributed_to", distinct=True) + subscribed = django_filters.BooleanFilter( + field_name="_", method="filter_subscribed" + ) class Meta: model = models.Channel - fields = ["q", "scope", "tag"] + fields = ["q", "scope", "tag", "subscribed"] hidden_content_fields_mapping = moderation_filters.USER_FILTER_CONFIG["CHANNEL"] + def filter_subscribed(self, queryset, name, value): + if not self.request.user.is_authenticated: + return queryset.none() + + emitted_follows = self.request.user.actor.emitted_follows.exclude( + target__channel__isnull=True + ) + + query = Q(actor__in=emitted_follows.values_list("target", flat=True)) + + if value is True: + return queryset.filter(query) + else: + return queryset.exclude(query) + class IncludeChannelsFilterSet(django_filters.FilterSet): """ diff --git a/api/tests/audio/test_filters.py b/api/tests/audio/test_filters.py new file mode 100644 index 000000000..c0cb9caa4 --- /dev/null +++ b/api/tests/audio/test_filters.py @@ -0,0 +1,32 @@ +from funkwhale_api.audio import filters +from funkwhale_api.audio import models + + +def test_channel_filter_subscribed_true(factories, mocker, queryset_equal_list): + user = factories["users.User"](with_actor=True) + channel = factories["audio.Channel"]() + other_channel = factories["audio.Channel"]() + factories["audio.Subscription"](target=channel.actor, actor=user.actor) + factories["audio.Subscription"](target=other_channel.actor) + + qs = models.Channel.objects.all() + filterset = filters.ChannelFilter( + {"subscribed": "true"}, request=mocker.Mock(user=user), queryset=qs + ) + + assert filterset.qs == [channel] + + +def test_channel_filter_subscribed_false(factories, mocker, queryset_equal_list): + user = factories["users.User"](with_actor=True) + channel = factories["audio.Channel"]() + other_channel = factories["audio.Channel"]() + factories["audio.Subscription"](target=channel.actor, actor=user.actor) + factories["audio.Subscription"](target=other_channel.actor) + + qs = models.Channel.objects.all() + filterset = filters.ChannelFilter( + {"subscribed": "false"}, request=mocker.Mock(user=user), queryset=qs + ) + + assert filterset.qs == [other_channel]