aboutsummaryrefslogtreecommitdiffstats
path: root/pydis_site
diff options
context:
space:
mode:
Diffstat (limited to 'pydis_site')
-rw-r--r--pydis_site/apps/api/migrations/0051_offtopicchannelname_used.py18
-rw-r--r--pydis_site/apps/api/models/bot/off_topic_channel_name.py5
-rw-r--r--pydis_site/apps/api/tests/test_off_topic_channel_names.py24
-rw-r--r--pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py29
4 files changed, 74 insertions, 2 deletions
diff --git a/pydis_site/apps/api/migrations/0051_offtopicchannelname_used.py b/pydis_site/apps/api/migrations/0051_offtopicchannelname_used.py
new file mode 100644
index 00000000..1b838aec
--- /dev/null
+++ b/pydis_site/apps/api/migrations/0051_offtopicchannelname_used.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.2.11 on 2020-03-30 10:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0050_remove_infractions_active_default_value'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ 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 29280c27..413cbfae 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
@@ -16,6 +16,11 @@ class OffTopicChannelName(ModelReprMixin, models.Model):
help_text="The actual channel name that will be used on our Discord server."
)
+ used = models.BooleanField(
+ default=False,
+ help_text="Whether or not this name has already been used during this rotation",
+ )
+
def __str__(self):
"""Returns the current off-topic name, for display purposes."""
return self.name
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 bd42cd81..06624d89 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
@@ -21,6 +21,12 @@ class UnauthenticatedTests(APISubdomainTestCase):
self.assertEqual(response.status_code, 401)
+ def test_cannot_read_off_topic_channel_name_list_with_random_item_and_mark_used_param(self):
+ url = reverse('bot:offtopicchannelname-list', host='api')
+ response = self.client.get(f'{url}?random_items=no&mark_used=true')
+
+ self.assertEqual(response.status_code, 401)
+
class EmptyDatabaseTests(APISubdomainTestCase):
def test_returns_empty_object(self):
@@ -59,8 +65,8 @@ class EmptyDatabaseTests(APISubdomainTestCase):
class ListTests(APISubdomainTestCase):
@classmethod
def setUpTestData(cls):
- cls.test_name = OffTopicChannelName.objects.create(name='lemons-lemonade-stand')
- cls.test_name_2 = OffTopicChannelName.objects.create(name='bbq-with-bisk')
+ 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)
def test_returns_name_in_list(self):
url = reverse('bot:offtopicchannelname-list', host='api')
@@ -82,6 +88,20 @@ class ListTests(APISubdomainTestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 1)
+ def test_returns_single_correct_item_with_mark_used_parameter_true_and_random_items_1(self):
+ url = reverse('bot:offtopicchannelname-list', host='api')
+ response = self.client.get(f'{url}?random_items=1&mark_used=true')
+
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.json(), [self.test_name.name])
+
+ def test_running_out_of_names_with_mark_used_parameter(self):
+ url = reverse('bot:offtopicchannelname-list', host='api')
+ response = self.client.get(f'{url}?random_items=2&mark_used=true')
+
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.json(), [self.test_name.name, self.test_name_2.name])
+
class CreationTests(APISubdomainTestCase):
def setUp(self):
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 d6da2399..4328c894 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
@@ -21,6 +21,10 @@ class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet):
If the `random_items` query parameter is given, for example using...
$ curl api.pythondiscord.local:8000/bot/off-topic-channel-names?random_items=5
... then the API will return `5` random items from the database.
+ If the `mark_used` query parameter is given like...
+ $ curl api.pydis.local:8000/bot/off-topic-channel-names?random_items=5&mark_used=true
+ ... then the API will mark returned `5` items `used`.
+ When running out of names, API will mark all names to not used and start new round.
#### Response format
Return a list of off-topic-channel names:
@@ -106,6 +110,31 @@ class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet):
'random_items': ["Must be a positive integer."]
})
+ if 'mark_used' in request.query_params and request.query_params['mark_used']:
+ queryset = self.get_queryset().order_by('?').exclude(used=True)[:random_count]
+ self.get_queryset().filter(
+ name__in=(query.name for query in queryset)
+ ).update(used=True)
+
+ # When client request more channel names than non-used names is available, start
+ # new round of names.
+ if len(queryset) < random_count:
+ # Get how much names still missing and don't fetch duplicate names.
+ need_more = random_count - len(queryset)
+ ext = self.get_queryset().order_by('?').exclude(
+ name__in=(query.name for query in queryset)
+ )[:need_more]
+
+ # Set all names `used` field to False except these that we just used.
+ self.get_queryset().exclude(name__in=(
+ query.name for query in ext)
+ ).update(used=False)
+ # Join original queryset (that had missing names)
+ # and extension with these missing names.
+ queryset = list(queryset) + list(ext)
+ serialized = self.serializer_class(queryset, many=True)
+ return Response(serialized.data)
+
queryset = self.get_queryset().order_by('?')[:random_count]
serialized = self.serializer_class(queryset, many=True)
return Response(serialized.data)