diff options
Diffstat (limited to 'pydis_site/apps/api')
5 files changed, 101 insertions, 30 deletions
diff --git a/pydis_site/apps/api/migrations/0070_auto_20210519_0545.py b/pydis_site/apps/api/migrations/0070_auto_20210519_0545.py new file mode 100644 index 00000000..dbd7ac91 --- /dev/null +++ b/pydis_site/apps/api/migrations/0070_auto_20210519_0545.py @@ -0,0 +1,23 @@ +# Generated by Django 3.0.14 on 2021-05-19 05:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('api', '0069_documentationlink_validators'), +    ] + +    operations = [ +        migrations.AddField( +            model_name='offtopicchannelname', +            name='active', +            field=models.BooleanField(default=True, help_text='Whether or not this name should be considered for naming channels.'), +        ), +        migrations.AlterField( +            model_name='offtopicchannelname', +            name='used', +            field=models.BooleanField(default=False, help_text='Whether or not this name has already been used during this rotation.'), +        ), +    ] diff --git a/pydis_site/apps/api/models/bot/off_topic_channel_name.py b/pydis_site/apps/api/models/bot/off_topic_channel_name.py index 403c7465..582c069e 100644 --- a/pydis_site/apps/api/models/bot/off_topic_channel_name.py +++ b/pydis_site/apps/api/models/bot/off_topic_channel_name.py @@ -18,7 +18,12 @@ class OffTopicChannelName(ModelReprMixin, models.Model):      used = models.BooleanField(          default=False, -        help_text="Whether or not this name has already been used during this rotation", +        help_text="Whether or not this name has already been used during this rotation.", +    ) + +    active = models.BooleanField( +        default=True, +        help_text="Whether or not this name should be considered for naming channels."      )      def __str__(self): diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index f47bedca..0d505675 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -1,4 +1,6 @@  """Converters from Django models to data interchange formats and back.""" +from typing import List +  from django.db.models.query import QuerySet  from django.db.utils import IntegrityError  from rest_framework.exceptions import NotFound @@ -200,16 +202,10 @@ class ExpandedInfractionSerializer(InfractionSerializer):          return ret -class OffTopicChannelNameSerializer(ModelSerializer): -    """A class providing (de-)serialization of `OffTopicChannelName` instances.""" +class OffTopicChannelNameListSerializer(ListSerializer): +    """Custom ListSerializer to override to_representation() when list views are triggered.""" -    class Meta: -        """Metadata defined for the Django REST Framework.""" - -        model = OffTopicChannelName -        fields = ('name',) - -    def to_representation(self, obj: OffTopicChannelName) -> str: +    def to_representation(self, objects: List[OffTopicChannelName]) -> List[str]:          """          Return the representation of this `OffTopicChannelName`. @@ -218,7 +214,18 @@ class OffTopicChannelNameSerializer(ModelSerializer):          Additionally, this allows off topic channel name routes to simply return an          array of names instead of objects, saving on bandwidth.          """ -        return obj.name +        return [obj.name for obj in objects] + + +class OffTopicChannelNameSerializer(ModelSerializer): +    """A class providing (de-)serialization of `OffTopicChannelName` instances.""" + +    class Meta: +        """Metadata defined for the Django REST Framework.""" + +        list_serializer_class = OffTopicChannelNameListSerializer +        model = OffTopicChannelName +        fields = ('name', 'used', 'active')  class ReminderSerializer(ModelSerializer): diff --git a/pydis_site/apps/api/tests/test_off_topic_channel_names.py b/pydis_site/apps/api/tests/test_off_topic_channel_names.py index 3ab8b22d..ebb1224a 100644 --- a/pydis_site/apps/api/tests/test_off_topic_channel_names.py +++ b/pydis_site/apps/api/tests/test_off_topic_channel_names.py @@ -65,8 +65,15 @@ class EmptyDatabaseTests(APISubdomainTestCase):  class ListTests(APISubdomainTestCase):      @classmethod      def setUpTestData(cls): -        cls.test_name = OffTopicChannelName.objects.create(name='lemons-lemonade-stand', used=False) -        cls.test_name_2 = OffTopicChannelName.objects.create(name='bbq-with-bisk', used=True) +        cls.test_name = OffTopicChannelName.objects.create( +            name='lemons-lemonade-stand', used=False, active=True +        ) +        cls.test_name_2 = OffTopicChannelName.objects.create( +            name='bbq-with-bisk', used=False, active=True +        ) +        cls.test_name_3 = OffTopicChannelName.objects.create( +            name="frozen-with-iceman", used=True, active=False +        )      def test_returns_name_in_list(self):          """Return all off-topic channel names.""" @@ -74,30 +81,55 @@ class ListTests(APISubdomainTestCase):          response = self.client.get(url)          self.assertEqual(response.status_code, 200) -        self.assertEqual( +        self.assertListEqual(              response.json(),              [                  self.test_name.name, -                self.test_name_2.name +                self.test_name_2.name, +                self.test_name_3.name              ]          ) -    def test_returns_single_item_with_random_items_param_set_to_1(self): +    def test_returns_two_items_with_random_items_param_set_to_2(self):          """Return not-used name instead used."""          url = reverse('bot:offtopicchannelname-list', host='api') -        response = self.client.get(f'{url}?random_items=1') +        response = self.client.get(f'{url}?random_items=2')          self.assertEqual(response.status_code, 200) -        self.assertEqual(len(response.json()), 1) -        self.assertEqual(response.json(), [self.test_name.name]) +        self.assertEqual(len(response.json()), 2) +        self.assertEqual(response.json(), [self.test_name.name, self.test_name_2.name])      def test_running_out_of_names_with_random_parameter(self):          """Reset names `used` parameter to `False` when running out of names."""          url = reverse('bot:offtopicchannelname-list', host='api') -        response = self.client.get(f'{url}?random_items=2') +        response = self.client.get(f'{url}?random_items=3')          self.assertEqual(response.status_code, 200) -        self.assertEqual(response.json(), [self.test_name.name, self.test_name_2.name]) +        self.assertListEqual( +            response.json(), [self.test_name.name, self.test_name_2.name, self.test_name_3.name] +        ) + +    def test_returns_inactive_ot_names(self): +        """Return inactive off topic names.""" +        url = reverse('bot:offtopicchannelname-list', host="api") +        response = self.client.get(f"{url}?active=false") + +        self.assertEqual(response.status_code, 200) +        self.assertEqual( +            response.json(), +            [self.test_name_3.name] +        ) + +    def test_returns_active_ot_names(self): +        """Return active off topic names.""" +        url = reverse('bot:offtopicchannelname-list', host="api") +        response = self.client.get(f"{url}?active=true") + +        self.assertEqual(response.status_code, 200) +        self.assertEqual( +            response.json(), +            [self.test_name.name, self.test_name_2.name] +        )  class CreationTests(APISubdomainTestCase): diff --git a/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py b/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py index 826ad25e..18ee84ea 100644 --- a/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py +++ b/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py @@ -1,18 +1,17 @@  from django.db.models import Case, Value, When  from django.db.models.query import QuerySet -from django.http.request import HttpRequest  from django.shortcuts import get_object_or_404  from rest_framework.exceptions import ParseError -from rest_framework.mixins import DestroyModelMixin +from rest_framework.request import Request  from rest_framework.response import Response  from rest_framework.status import HTTP_201_CREATED -from rest_framework.viewsets import ViewSet +from rest_framework.viewsets import ModelViewSet  from pydis_site.apps.api.models.bot.off_topic_channel_name import OffTopicChannelName  from pydis_site.apps.api.serializers import OffTopicChannelNameSerializer -class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet): +class OffTopicChannelNameViewSet(ModelViewSet):      """      View of off-topic channel names used by the bot to rotate our off-topic names on a daily basis. @@ -69,11 +68,11 @@ class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet):          name = self.kwargs[self.lookup_field]          return get_object_or_404(queryset, name=name) -    def get_queryset(self) -> QuerySet: +    def get_queryset(self, **kwargs) -> QuerySet:          """Returns a queryset that covers the entire OffTopicChannelName table.""" -        return OffTopicChannelName.objects.all() +        return OffTopicChannelName.objects.filter(**kwargs) -    def create(self, request: HttpRequest) -> Response: +    def create(self, request: Request, *args, **kwargs) -> Response:          """          DRF method for creating a new OffTopicChannelName. @@ -91,7 +90,7 @@ class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet):                  'name': ["This query parameter is required."]              }) -    def list(self, request: HttpRequest) -> Response: +    def list(self, request: Request, *args, **kwargs) -> Response:          """          DRF method for listing OffTopicChannelName entries. @@ -133,6 +132,11 @@ class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet):              serialized = self.serializer_class(queryset, many=True)              return Response(serialized.data) -        queryset = self.get_queryset() +        params = {} + +        if active_param := request.query_params.get("active"): +            params["active"] = active_param.lower() == "true" + +        queryset = self.get_queryset(**params)          serialized = self.serializer_class(queryset, many=True)          return Response(serialized.data)  |