aboutsummaryrefslogtreecommitdiffstats
path: root/pydis_site/apps/api
diff options
context:
space:
mode:
Diffstat (limited to 'pydis_site/apps/api')
-rw-r--r--pydis_site/apps/api/migrations/0070_auto_20210519_0545.py23
-rw-r--r--pydis_site/apps/api/models/bot/off_topic_channel_name.py7
-rw-r--r--pydis_site/apps/api/serializers.py29
-rw-r--r--pydis_site/apps/api/tests/test_off_topic_channel_names.py57
-rw-r--r--pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py22
5 files changed, 105 insertions, 33 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..957c85f3 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,25 +202,30 @@ 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`.
+ Return a list representing a list of `OffTopicChannelName`.
This only returns the name of the off topic channel name. As the model
only has a single attribute, it is unnecessary to create a nested dictionary.
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..34dde7c6 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."""
@@ -75,29 +82,55 @@ class ListTests(APISubdomainTestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(
- response.json(),
- [
+ set(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(set(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.assertEqual(
+ set(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(
+ set(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)