diff options
author | 2023-03-21 16:22:36 +0200 | |
---|---|---|
committer | 2023-03-21 16:31:57 +0200 | |
commit | a1a8e49f097739bbd2c989e1568fe4fe18946bbf (patch) | |
tree | 0660e01117b1a179e7115484ec44ca53f38437f2 /pydis_site/apps/api | |
parent | Fix filter serializers for false-y values (diff) | |
parent | Merge 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.py | 18 | ||||
-rw-r--r-- | pydis_site/apps/api/migrations/0087_alter_mute_to_timeout.py | 25 | ||||
-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.py | 11 | ||||
-rw-r--r-- | pydis_site/apps/api/serializers.py | 3 | ||||
-rw-r--r-- | pydis_site/apps/api/tests/test_filters.py | 6 | ||||
-rw-r--r-- | pydis_site/apps/api/tests/test_infractions.py | 24 | ||||
-rw-r--r-- | pydis_site/apps/api/viewsets/bot/infraction.py | 8 |
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, |