aboutsummaryrefslogtreecommitdiffstats
path: root/pydis_site/apps/api
diff options
context:
space:
mode:
authorGravatar mbaruh <[email protected]>2023-03-21 16:22:36 +0200
committerGravatar mbaruh <[email protected]>2023-03-21 16:31:57 +0200
commita1a8e49f097739bbd2c989e1568fe4fe18946bbf (patch)
tree0660e01117b1a179e7115484ec44ca53f38437f2 /pydis_site/apps/api
parentFix filter serializers for false-y values (diff)
parentMerge pull request #908 from python-discord/fix-ci (diff)
Merge branch 'main' into new-filter-schema
Diffstat (limited to 'pydis_site/apps/api')
-rw-r--r--pydis_site/apps/api/migrations/0086_infraction_jump_url.py18
-rw-r--r--pydis_site/apps/api/migrations/0087_alter_mute_to_timeout.py25
-rw-r--r--pydis_site/apps/api/migrations/0088_new_filter_schema.py (renamed from pydis_site/apps/api/migrations/0086_new_filter_schema.py)6
-rw-r--r--pydis_site/apps/api/migrations/0089_unique_constraint_filters.py (renamed from pydis_site/apps/api/migrations/0087_unique_constraint_filters.py)2
-rw-r--r--pydis_site/apps/api/migrations/0090_unique_filter_list.py (renamed from pydis_site/apps/api/migrations/0088_unique_filter_list.py)2
-rw-r--r--pydis_site/apps/api/migrations/0091_antispam_filter_list.py (renamed from pydis_site/apps/api/migrations/0089_antispam_filter_list.py)4
-rw-r--r--pydis_site/apps/api/models/bot/infraction.py11
-rw-r--r--pydis_site/apps/api/serializers.py3
-rw-r--r--pydis_site/apps/api/tests/test_filters.py6
-rw-r--r--pydis_site/apps/api/tests/test_infractions.py24
-rw-r--r--pydis_site/apps/api/viewsets/bot/infraction.py8
11 files changed, 82 insertions, 27 deletions
diff --git a/pydis_site/apps/api/migrations/0086_infraction_jump_url.py b/pydis_site/apps/api/migrations/0086_infraction_jump_url.py
new file mode 100644
index 00000000..7ae65751
--- /dev/null
+++ b/pydis_site/apps/api/migrations/0086_infraction_jump_url.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.1.7 on 2023-03-10 17:25
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0085_add_thread_id_to_nominations'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='infraction',
+ name='jump_url',
+ field=models.URLField(default=None, help_text='The jump url to message invoking the infraction.', max_length=88, null=True),
+ ),
+ ]
diff --git a/pydis_site/apps/api/migrations/0087_alter_mute_to_timeout.py b/pydis_site/apps/api/migrations/0087_alter_mute_to_timeout.py
new file mode 100644
index 00000000..8a826ba5
--- /dev/null
+++ b/pydis_site/apps/api/migrations/0087_alter_mute_to_timeout.py
@@ -0,0 +1,25 @@
+from django.apps.registry import Apps
+from django.db import migrations, models
+
+import pydis_site.apps.api.models
+
+
+def rename_type(apps: Apps, _) -> None:
+ infractions: pydis_site.apps.api.models.Infraction = apps.get_model("api", "Infraction")
+ infractions.objects.filter(type="mute").update(type="timeout")
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0086_infraction_jump_url'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='infraction',
+ name='type',
+ field=models.CharField(choices=[('note', 'Note'), ('warning', 'Warning'), ('watch', 'Watch'), ('timeout', 'Timeout'), ('kick', 'Kick'), ('ban', 'Ban'), ('superstar', 'Superstar'), ('voice_ban', 'Voice Ban'), ('voice_mute', 'Voice Mute')], help_text='The type of the infraction.', max_length=10),
+ ),
+ migrations.RunPython(rename_type, migrations.RunPython.noop)
+ ]
diff --git a/pydis_site/apps/api/migrations/0086_new_filter_schema.py b/pydis_site/apps/api/migrations/0088_new_filter_schema.py
index 5da3a3b1..46756781 100644
--- a/pydis_site/apps/api/migrations/0086_new_filter_schema.py
+++ b/pydis_site/apps/api/migrations/0088_new_filter_schema.py
@@ -89,7 +89,7 @@ def forward(apps: Apps, schema_editor: BaseDatabaseSchemaEditor) -> None:
class Migration(migrations.Migration):
dependencies = [
- ('api', '0085_add_thread_id_to_nominations'),
+ ('api', '0087_alter_mute_to_timeout'),
]
operations = [
@@ -114,7 +114,7 @@ class Migration(migrations.Migration):
('enabled', models.BooleanField(help_text='Whether this filter is currently enabled.', null=True)),
('dm_content', models.CharField(help_text='The DM to send to a user triggering this filter.', max_length=1000, null=True, blank=True)),
('dm_embed', models.CharField(help_text='The content of the DM embed', max_length=2000, null=True, blank=True)),
- ('infraction_type', models.CharField(choices=[('NONE', 'None'), ('NOTE', 'Note'), ('WARNING', 'Warning'), ('WATCH', 'Watch'), ('MUTE', 'Mute'), ('KICK', 'Kick'), ('BAN', 'Ban'), ('SUPERSTAR', 'Superstar'), ('VOICE_BAN', 'Voice Ban'), ('VOICE_MUTE', 'Voice Mute')], help_text='The infraction to apply to this user.', max_length=10, null=True)),
+ ('infraction_type', models.CharField(choices=[('NONE', 'None'), ('NOTE', 'Note'), ('WARNING', 'Warning'), ('WATCH', 'Watch'), ('TIMEOUT', 'Timeout'), ('KICK', 'Kick'), ('BAN', 'Ban'), ('SUPERSTAR', 'Superstar'), ('VOICE_BAN', 'Voice Ban'), ('VOICE_MUTE', 'Voice Mute')], help_text='The infraction to apply to this user.', max_length=10, null=True)),
('infraction_reason', models.CharField(help_text='The reason to give for the infraction.', max_length=1000, null=True, blank=True)),
('infraction_duration', models.DurationField(help_text='The duration of the infraction. 0 for permanent.', null=True)),
('infraction_channel', models.BigIntegerField(validators=(MinValueValidator(limit_value=0, message="Channel IDs cannot be negative."),), help_text="Channel in which to send the infraction.", null=True)),
@@ -141,7 +141,7 @@ class Migration(migrations.Migration):
('enabled', models.BooleanField(help_text='Whether this filter is currently enabled.')),
('dm_content', models.CharField(help_text='The DM to send to a user triggering this filter.', max_length=1000, blank=True)),
('dm_embed', models.CharField(help_text='The content of the DM embed', max_length=2000, blank=True)),
- ('infraction_type', models.CharField(choices=[('NONE', 'None'), ('NOTE', 'Note'), ('WARNING', 'Warning'), ('WATCH', 'Watch'), ('MUTE', 'Mute'), ('KICK', 'Kick'), ('BAN', 'Ban'), ('SUPERSTAR', 'Superstar'), ('VOICE_BAN', 'Voice Ban'), ('VOICE_MUTE', 'Voice Mute')], help_text='The infraction to apply to this user.', max_length=10)),
+ ('infraction_type', models.CharField(choices=[('NONE', 'None'), ('NOTE', 'Note'), ('WARNING', 'Warning'), ('WATCH', 'Watch'), ('TIMEOUT', 'Timeout'), ('KICK', 'Kick'), ('BAN', 'Ban'), ('SUPERSTAR', 'Superstar'), ('VOICE_BAN', 'Voice Ban'), ('VOICE_MUTE', 'Voice Mute')], help_text='The infraction to apply to this user.', max_length=10)),
('infraction_reason', models.CharField(help_text='The reason to give for the infraction.', max_length=1000, blank=True)),
('infraction_duration', models.DurationField(help_text='The duration of the infraction. 0 for permanent.')),
('infraction_channel', models.BigIntegerField(validators=(MinValueValidator(limit_value=0, message="Channel IDs cannot be negative."),), help_text="Channel in which to send the infraction.")),
diff --git a/pydis_site/apps/api/migrations/0087_unique_constraint_filters.py b/pydis_site/apps/api/migrations/0089_unique_constraint_filters.py
index 910e7b1b..d6f32342 100644
--- a/pydis_site/apps/api/migrations/0087_unique_constraint_filters.py
+++ b/pydis_site/apps/api/migrations/0089_unique_constraint_filters.py
@@ -4,7 +4,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('api', '0086_new_filter_schema'),
+ ('api', '0088_new_filter_schema'),
]
operations = [
diff --git a/pydis_site/apps/api/migrations/0088_unique_filter_list.py b/pydis_site/apps/api/migrations/0090_unique_filter_list.py
index 98d14e2b..cef2faa3 100644
--- a/pydis_site/apps/api/migrations/0088_unique_filter_list.py
+++ b/pydis_site/apps/api/migrations/0090_unique_filter_list.py
@@ -91,7 +91,7 @@ def create_unique_list(apps: Apps, _):
class Migration(migrations.Migration):
dependencies = [
- ('api', '0087_unique_constraint_filters'),
+ ('api', '0089_unique_constraint_filters'),
]
operations = [
diff --git a/pydis_site/apps/api/migrations/0089_antispam_filter_list.py b/pydis_site/apps/api/migrations/0091_antispam_filter_list.py
index 284d87e7..58ffa4a4 100644
--- a/pydis_site/apps/api/migrations/0089_antispam_filter_list.py
+++ b/pydis_site/apps/api/migrations/0091_antispam_filter_list.py
@@ -22,7 +22,7 @@ def create_antispam_list(apps: Apps, _):
enabled=True,
dm_content="",
dm_embed="",
- infraction_type="MUTE",
+ infraction_type="TIMEOUT",
infraction_reason="",
infraction_duration=timedelta(seconds=600),
infraction_channel=0,
@@ -41,7 +41,7 @@ def create_antispam_list(apps: Apps, _):
class Migration(migrations.Migration):
dependencies = [
- ('api', '0088_unique_filter_list'),
+ ('api', '0090_unique_filter_list'),
]
operations = [
diff --git a/pydis_site/apps/api/models/bot/infraction.py b/pydis_site/apps/api/models/bot/infraction.py
index 218ee5ec..381b5b9d 100644
--- a/pydis_site/apps/api/models/bot/infraction.py
+++ b/pydis_site/apps/api/models/bot/infraction.py
@@ -12,7 +12,7 @@ class Infraction(ModelReprMixin, models.Model):
("note", "Note"),
("warning", "Warning"),
("watch", "Watch"),
- ("mute", "Mute"),
+ ("timeout", "Timeout"),
("kick", "Kick"),
("ban", "Ban"),
("superstar", "Superstar"),
@@ -69,6 +69,15 @@ class Infraction(ModelReprMixin, models.Model):
help_text="Whether a DM was sent to the user when infraction was applied."
)
+ jump_url = models.URLField(
+ default=None,
+ null=True,
+ max_length=88,
+ help_text=(
+ "The jump url to message invoking the infraction."
+ )
+ )
+
def __str__(self):
"""Returns some info on the current infraction, for display purposes."""
s = f"#{self.id}: {self.type} on {self.user_id}"
diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py
index f4d64ad0..fe3c1dd2 100644
--- a/pydis_site/apps/api/serializers.py
+++ b/pydis_site/apps/api/serializers.py
@@ -427,7 +427,8 @@ class InfractionSerializer(ModelSerializer):
'type',
'reason',
'hidden',
- 'dm_sent'
+ 'dm_sent',
+ 'jump_url'
)
def validate(self, attrs: dict) -> dict:
diff --git a/pydis_site/apps/api/tests/test_filters.py b/pydis_site/apps/api/tests/test_filters.py
index 62de23c4..f36e0617 100644
--- a/pydis_site/apps/api/tests/test_filters.py
+++ b/pydis_site/apps/api/tests/test_filters.py
@@ -74,7 +74,7 @@ def get_test_sequences() -> Dict[str, TestSequence]:
"enabled": False,
"dm_content": "testing testing",
"dm_embed": "one two three",
- "infraction_type": "MUTE",
+ "infraction_type": "TIMEOUT",
"infraction_reason": "stop testing",
"infraction_duration": timedelta(seconds=10.5),
"infraction_channel": 123,
@@ -274,7 +274,7 @@ class FilterValidationTests(AuthenticatedAPITestCase):
({"infraction_reason": "hi"}, {}, 400),
({"infraction_duration": timedelta(seconds=10)}, {}, 400),
({"infraction_reason": "hi"}, {"infraction_type": "NOTE"}, 200),
- ({"infraction_duration": timedelta(seconds=10)}, {"infraction_type": "MUTE"}, 200),
+ ({"infraction_duration": timedelta(seconds=10)}, {"infraction_type": "TIMEOUT"}, 200),
({"enabled_channels": ["admins"]}, {}, 200),
({"disabled_channels": ["123"]}, {}, 200),
({"enabled_categories": ["CODE JAM"]}, {}, 200),
@@ -314,7 +314,7 @@ class FilterValidationTests(AuthenticatedAPITestCase):
({"infraction_reason": "hi"}, 400),
({"infraction_duration": timedelta(seconds=10)}, 400),
({"infraction_reason": "hi", "infraction_type": "NOTE"}, 200),
- ({"infraction_duration": timedelta(seconds=10), "infraction_type": "MUTE"}, 200),
+ ({"infraction_duration": timedelta(seconds=10), "infraction_type": "TIMEOUT"}, 200),
({"enabled_channels": ["admins"]}, 200), ({"disabled_channels": ["123"]}, 200),
({"enabled_categories": ["CODE JAM"]}, 200),
({"disabled_categories": ["CODE JAM"]}, 200),
diff --git a/pydis_site/apps/api/tests/test_infractions.py b/pydis_site/apps/api/tests/test_infractions.py
index 89ee4e23..ceb5591b 100644
--- a/pydis_site/apps/api/tests/test_infractions.py
+++ b/pydis_site/apps/api/tests/test_infractions.py
@@ -68,10 +68,10 @@ class InfractionTests(AuthenticatedAPITestCase):
active=False,
inserted_at=dt(2020, 10, 10, 0, 1, 0, tzinfo=timezone.utc),
)
- cls.mute_permanent = Infraction.objects.create(
+ cls.timeout_permanent = Infraction.objects.create(
user_id=cls.user.id,
actor_id=cls.user.id,
- type='mute',
+ type='timeout',
reason='He has a filthy mouth and I am his soap.',
active=True,
inserted_at=dt(2020, 10, 10, 0, 2, 0, tzinfo=timezone.utc),
@@ -107,7 +107,7 @@ class InfractionTests(AuthenticatedAPITestCase):
self.assertEqual(len(infractions), 5)
self.assertEqual(infractions[0]['id'], self.voiceban_expires_later.id)
self.assertEqual(infractions[1]['id'], self.superstar_expires_soon.id)
- self.assertEqual(infractions[2]['id'], self.mute_permanent.id)
+ self.assertEqual(infractions[2]['id'], self.timeout_permanent.id)
self.assertEqual(infractions[3]['id'], self.ban_inactive.id)
self.assertEqual(infractions[4]['id'], self.ban_hidden.id)
@@ -134,7 +134,7 @@ class InfractionTests(AuthenticatedAPITestCase):
def test_filter_permanent_false(self):
url = reverse('api:bot:infraction-list')
- response = self.client.get(f'{url}?type=mute&permanent=false')
+ response = self.client.get(f'{url}?type=timeout&permanent=false')
self.assertEqual(response.status_code, 200)
infractions = response.json()
@@ -143,12 +143,12 @@ class InfractionTests(AuthenticatedAPITestCase):
def test_filter_permanent_true(self):
url = reverse('api:bot:infraction-list')
- response = self.client.get(f'{url}?type=mute&permanent=true')
+ response = self.client.get(f'{url}?type=timeout&permanent=true')
self.assertEqual(response.status_code, 200)
infractions = response.json()
- self.assertEqual(infractions[0]['id'], self.mute_permanent.id)
+ self.assertEqual(infractions[0]['id'], self.timeout_permanent.id)
def test_filter_after(self):
url = reverse('api:bot:infraction-list')
@@ -241,7 +241,7 @@ class InfractionTests(AuthenticatedAPITestCase):
def test_filter_manytypes(self):
url = reverse('api:bot:infraction-list')
- response = self.client.get(f'{url}?types=mute,ban')
+ response = self.client.get(f'{url}?types=timeout,ban')
self.assertEqual(response.status_code, 200)
infractions = response.json()
@@ -249,7 +249,7 @@ class InfractionTests(AuthenticatedAPITestCase):
def test_types_type_invalid(self):
url = reverse('api:bot:infraction-list')
- response = self.client.get(f'{url}?types=mute,ban&type=superstar')
+ response = self.client.get(f'{url}?types=timeout,ban&type=superstar')
self.assertEqual(response.status_code, 400)
errors = list(response.json())
@@ -519,7 +519,7 @@ class CreationTests(AuthenticatedAPITestCase):
def test_returns_400_for_second_active_infraction_of_the_same_type(self):
"""Test if the API rejects a second active infraction of the same type for a given user."""
url = reverse('api:bot:infraction-list')
- active_infraction_types = ('mute', 'ban', 'superstar')
+ active_infraction_types = ('timeout', 'ban', 'superstar')
for infraction_type in active_infraction_types:
with self.subTest(infraction_type=infraction_type):
@@ -562,7 +562,7 @@ class CreationTests(AuthenticatedAPITestCase):
first_active_infraction = {
'user': self.user.id,
'actor': self.user.id,
- 'type': 'mute',
+ 'type': 'timeout',
'reason': 'Be silent!',
'hidden': True,
'active': True,
@@ -649,9 +649,9 @@ class CreationTests(AuthenticatedAPITestCase):
Infraction.objects.create(
user=self.user,
actor=self.user,
- type="mute",
+ type="timeout",
active=True,
- reason="The first active mute"
+ reason="The first active timeout"
)
def test_unique_constraint_accepts_active_infractions_for_different_users(self):
diff --git a/pydis_site/apps/api/viewsets/bot/infraction.py b/pydis_site/apps/api/viewsets/bot/infraction.py
index 93d29391..ec8b83a1 100644
--- a/pydis_site/apps/api/viewsets/bot/infraction.py
+++ b/pydis_site/apps/api/viewsets/bot/infraction.py
@@ -72,7 +72,8 @@ class InfractionViewSet(
... 'type': 'ban',
... 'reason': 'He terk my jerb!',
... 'hidden': True,
- ... 'dm_sent': True
+ ... 'dm_sent': True,
+ ... 'jump_url': '<discord message link>'
... }
... ]
@@ -103,7 +104,8 @@ class InfractionViewSet(
... 'type': 'ban',
... 'reason': 'He terk my jerb!',
... 'user': 172395097705414656,
- ... 'dm_sent': False
+ ... 'dm_sent': False,
+ ... 'jump_url': '<discord message link>'
... }
#### Response format
@@ -138,7 +140,7 @@ class InfractionViewSet(
#### Status codes
- 204: returned on success
- - 404: if a infraction with the given `id` does not exist
+ - 404: if an infraction with the given `id` does not exist
### Expanded routes
All routes support expansion of `user` and `actor` in responses. To use an expanded route,