Skip to content

Commit aa620e4

Browse files
authored
Merge branch 'main' into contrib-streamline
2 parents 2470557 + 769bc00 commit aa620e4

File tree

28 files changed

+538
-41
lines changed

28 files changed

+538
-41
lines changed

.github/ISSUE_TEMPLATE/resource_suggestion.md

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by Django 3.1.14 on 2022-02-19 16:26
2+
3+
import django.core.validators
4+
from django.db import migrations, models
5+
import pydis_site.apps.api.models.mixins
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('api', '0080_add_aoc_tables'),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='BumpedThread',
17+
fields=[
18+
('thread_id', models.BigIntegerField(help_text='The thread ID that should be bumped.', primary_key=True, serialize=False, validators=[django.core.validators.MinValueValidator(limit_value=0, message='Thread IDs cannot be negative.')], verbose_name='Thread ID')),
19+
],
20+
bases=(pydis_site.apps.api.models.mixins.ModelReprMixin, models.Model),
21+
),
22+
]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 3.1.14 on 2022-04-21 23:29
2+
3+
import django.core.validators
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('api', '0081_bumpedthread'),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name='offtopicchannelname',
16+
name='name',
17+
field=models.CharField(help_text='The actual channel name that will be used on our Discord server.', max_length=96, primary_key=True, serialize=False, validators=[django.core.validators.RegexValidator(regex="^[a-z0-9\\U0001d5a0-\\U0001d5b9-ǃ?’'<>⧹⧸]+$")]),
18+
),
19+
]

pydis_site/apps/api/models/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# flake8: noqa
22
from .bot import (
3-
FilterList,
43
BotSetting,
4+
BumpedThread,
55
DocumentationLink,
66
DeletedMessage,
7+
FilterList,
78
Infraction,
89
Message,
910
MessageDeletionContext,

pydis_site/apps/api/models/bot/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# flake8: noqa
2-
from .filter_list import FilterList
32
from .bot_setting import BotSetting
3+
from .bumped_thread import BumpedThread
44
from .deleted_message import DeletedMessage
55
from .documentation_link import DocumentationLink
6+
from .filter_list import FilterList
67
from .infraction import Infraction
78
from .message import Message
89
from .aoc_completionist_block import AocCompletionistBlock
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from django.core.validators import MinValueValidator
2+
from django.db import models
3+
4+
from pydis_site.apps.api.models.mixins import ModelReprMixin
5+
6+
7+
class BumpedThread(ModelReprMixin, models.Model):
8+
"""A list of thread IDs to be bumped."""
9+
10+
thread_id = models.BigIntegerField(
11+
primary_key=True,
12+
help_text=(
13+
"The thread ID that should be bumped."
14+
),
15+
validators=(
16+
MinValueValidator(
17+
limit_value=0,
18+
message="Thread IDs cannot be negative."
19+
),
20+
),
21+
verbose_name="Thread ID",
22+
)

pydis_site/apps/api/models/bot/off_topic_channel_name.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class OffTopicChannelName(ModelReprMixin, models.Model):
1111
primary_key=True,
1212
max_length=96,
1313
validators=(
14-
RegexValidator(regex=r"^[a-z0-9\U0001d5a0-\U0001d5b9-ǃ?’'<>]+$"),
14+
RegexValidator(regex=r"^[a-z0-9\U0001d5a0-\U0001d5b9-ǃ?’'<>⧹⧸]+$"),
1515
),
1616
help_text="The actual channel name that will be used on our Discord server."
1717
)

pydis_site/apps/api/serializers.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
AocAccountLink,
1717
AocCompletionistBlock,
1818
BotSetting,
19+
BumpedThread,
1920
DeletedMessage,
2021
DocumentationLink,
2122
FilterList,
@@ -41,6 +42,32 @@ class Meta:
4142
fields = ('name', 'data')
4243

4344

45+
class ListBumpedThreadSerializer(ListSerializer):
46+
"""Custom ListSerializer to override to_representation() when list views are triggered."""
47+
48+
def to_representation(self, objects: list[BumpedThread]) -> int:
49+
"""
50+
Used by the `ListModelMixin` to return just the list of bumped thread ids.
51+
52+
Only the thread_id field is useful, hence it is unnecessary to create a nested dictionary.
53+
54+
Additionally, this allows bumped thread routes to simply return an
55+
array of thread_id ints instead of objects, saving on bandwidth.
56+
"""
57+
return [obj.thread_id for obj in objects]
58+
59+
60+
class BumpedThreadSerializer(ModelSerializer):
61+
"""A class providing (de-)serialization of `BumpedThread` instances."""
62+
63+
class Meta:
64+
"""Metadata defined for the Django REST Framework."""
65+
66+
list_serializer_class = ListBumpedThreadSerializer
67+
model = BumpedThread
68+
fields = ('thread_id',)
69+
70+
4471
class DeletedMessageSerializer(ModelSerializer):
4572
"""
4673
A class providing (de-)serialization of `DeletedMessage` instances.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from django.urls import reverse
2+
3+
from .base import AuthenticatedAPITestCase
4+
from ..models import BumpedThread
5+
6+
7+
class UnauthedBumpedThreadAPITests(AuthenticatedAPITestCase):
8+
def setUp(self):
9+
super().setUp()
10+
self.client.force_authenticate(user=None)
11+
12+
def test_detail_lookup_returns_401(self):
13+
url = reverse('api:bot:bumpedthread-detail', args=(1,))
14+
response = self.client.get(url)
15+
16+
self.assertEqual(response.status_code, 401)
17+
18+
def test_list_returns_401(self):
19+
url = reverse('api:bot:bumpedthread-list')
20+
response = self.client.get(url)
21+
22+
self.assertEqual(response.status_code, 401)
23+
24+
def test_create_returns_401(self):
25+
url = reverse('api:bot:bumpedthread-list')
26+
response = self.client.post(url, {"thread_id": 3})
27+
28+
self.assertEqual(response.status_code, 401)
29+
30+
def test_delete_returns_401(self):
31+
url = reverse('api:bot:bumpedthread-detail', args=(1,))
32+
response = self.client.delete(url)
33+
34+
self.assertEqual(response.status_code, 401)
35+
36+
37+
class BumpedThreadAPITests(AuthenticatedAPITestCase):
38+
@classmethod
39+
def setUpTestData(cls):
40+
cls.thread1 = BumpedThread.objects.create(
41+
thread_id=1234,
42+
)
43+
44+
def test_returns_bumped_threads_as_flat_list(self):
45+
url = reverse('api:bot:bumpedthread-list')
46+
47+
response = self.client.get(url)
48+
self.assertEqual(response.status_code, 200)
49+
self.assertEqual(response.json(), [1234])
50+
51+
def test_returns_204_for_existing_data(self):
52+
url = reverse('api:bot:bumpedthread-detail', args=(1234,))
53+
54+
response = self.client.get(url)
55+
self.assertEqual(response.status_code, 204)
56+
self.assertEqual(response.content, b"")
57+
58+
def test_returns_404_for_non_existing_data(self):
59+
url = reverse('api:bot:bumpedthread-detail', args=(42,))
60+
61+
response = self.client.get(url)
62+
self.assertEqual(response.status_code, 404)
63+
self.assertEqual(response.json(), {"detail": "Not found."})

pydis_site/apps/api/urls.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
AocAccountLinkViewSet,
77
AocCompletionistBlockViewSet,
88
BotSettingViewSet,
9+
BumpedThreadViewSet,
910
DeletedMessageViewSet,
1011
DocumentationLinkViewSet,
1112
FilterListViewSet,
@@ -21,13 +22,21 @@
2122
# https://www.django-rest-framework.org/api-guide/routers/#defaultrouter
2223
bot_router = DefaultRouter(trailing_slash=False)
2324
bot_router.register(
24-
'filter-lists',
25-
FilterListViewSet
25+
"aoc-account-links",
26+
AocAccountLinkViewSet
27+
)
28+
bot_router.register(
29+
"aoc-completionist-blocks",
30+
AocCompletionistBlockViewSet
2631
)
2732
bot_router.register(
2833
'bot-settings',
2934
BotSettingViewSet
3035
)
36+
bot_router.register(
37+
'bumped-threads',
38+
BumpedThreadViewSet
39+
)
3140
bot_router.register(
3241
'deleted-messages',
3342
DeletedMessageViewSet
@@ -37,12 +46,8 @@
3746
DocumentationLinkViewSet
3847
)
3948
bot_router.register(
40-
"aoc-account-links",
41-
AocAccountLinkViewSet
42-
)
43-
bot_router.register(
44-
"aoc-completionist-blocks",
45-
AocCompletionistBlockViewSet
49+
'filter-lists',
50+
FilterListViewSet
4651
)
4752
bot_router.register(
4853
'infractions',

0 commit comments

Comments
 (0)