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 | |
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')
16 files changed, 96 insertions, 42 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, diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md index c9566d23..edfd7ac1 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md @@ -10,7 +10,7 @@ You should have already forked the [`sir-lancebot`](https://github.com/python-di Remember to ensure that you have read the [contributing guidelines](../contributing-guidelines) in full before you start contributing. ### Requirements -- [Python 3.9](https://www.python.org/downloads/) +- [Python 3.10.*](https://www.python.org/downloads/) - [Poetry](https://github.com/python-poetry/poetry#installation) - [Git](https://git-scm.com/downloads) - [Windows Installer](https://git-scm.com/download/win) @@ -59,7 +59,7 @@ You will need your own test server and bot account on Discord to test your chang * `#dev-log` * `#sir-lancebot-commands` 4. Create the following roles: - * `@Admin` + * `@Admins` 5. Note down the IDs for your server, as well as any channels and roles created. * [**Learn how to obtain the ID of a server, channel or role here.**](../setting-test-server-and-bot-account#obtain-the-ids) diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md index 51587aac..3862fb2e 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md @@ -10,12 +10,12 @@ The following variables are needed for running Sir Lancebot: | -------- | -------- | | `BOT_TOKEN` | Bot Token from the [Discord developer portal](https://discord.com/developers/applications) | | `BOT_GUILD` | ID of the Discord Server | -| `BOT_ADMIN_ROLE_ID` | ID of the role @Admins | -| `ROLE_HELPERS` | ID of the role @Helpers | -| `CHANNEL_ANNOUNCEMENTS` | ID of the #announcements channel | -| `CHANNEL_DEVLOG` | ID of the #dev-log channel | -| `CHANNEL_COMMUNITY_BOT_COMMANDS` | ID of the #sir-lancebot-commands channel | -| `CHANNEL_REDDIT` | ID of the #reddit channel | +| `BOT_ADMIN_ROLE_ID` | ID of the role `@Admins` | +| `ROLE_HELPERS` | ID of the role `@Helpers` | +| `CHANNEL_ANNOUNCEMENTS` | ID of the `#announcements` channel | +| `CHANNEL_DEVLOG` | ID of the `#dev-log` channel | +| `CHANNEL_COMMUNITY_BOT_COMMANDS` | ID of the `#sir-lancebot-commands` channel | +| `CHANNEL_REDDIT` | ID of the `#reddit` channel | --- ## Debug Variables @@ -32,8 +32,7 @@ Additionally, you may find the following environment variables useful during dev | `REDIS_PASSWORD` | | | `USE_FAKEREDIS` | If the FakeRedis module should be used. Set this to true if you don't have a Redis database setup. | | `BOT_SENTRY_DSN` | The DSN of the sentry monitor. | -| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of `\:emoji:`. | - +| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of sending `\:emoji:` on discord. | --- ## Tokens/APIs @@ -66,8 +65,8 @@ These variables might come in handy while working on certain cogs: | Advent of Code | `AOC_ROLE_ID` | ID of the advent of code role. | Advent of Code | `AOC_IGNORED_DAYS` | Comma separated list of days to ignore while calculating score. | | Advent of Code | `AOC_YEAR` | Debug variable to change the year used for AoC. | -| Advent of Code | `AOC_CHANNEL_ID` | The ID of the #advent-of-code channel | -| Advent of Code | `AOC_COMMANDS_CHANNEL_ID` | The ID of the #advent-of-code-commands channel | +| Advent of Code | `AOC_CHANNEL_ID` | The ID of the `#advent-of-code` channel | +| Advent of Code | `AOC_COMMANDS_CHANNEL_ID` | The ID of the `#advent-of-code-commands` channel | | Advent of Code | `AOC_FALLBACK_SESSION` | | | Advent of Code | `AOC_SESSION_COOKIE` | | | Valentines | `LOVEFEST_ROLE_ID` | | diff --git a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md index 9d523b4b..92eb52a3 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md +++ b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md @@ -11,7 +11,7 @@ To help prevent leaking your token, you should ensure that you don't upload it to an open source program/website, such as replit and github, as they show your code publicly. The best practice for storing tokens is generally utilising .env files -([click here](https://vcokltfre.dev/tips/tokens/.) for more information on storing tokens safely). +([click here](https://tutorial.vco.sh/tips/tokens/) for more information on storing tokens safely). # What should I do if my token does get leaked? diff --git a/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md b/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md index ae34c2b4..6d9f433e 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md +++ b/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md @@ -2,7 +2,7 @@ title: Why JSON is unsuitable as a database description: The many reasons why you shouldn't use JSON as a database, and instead opt for SQL. relevant_links: - Tips on Storing Data: https://tutorial.vcokltfre.dev/tips/storage/ + Tips on Storing Data: https://tutorial.vco.sh/tips/storage/ --- JSON, quite simply, is not a database. It's not designed to be a data storage format, diff --git a/pydis_site/apps/resources/resources/vcokltfre_discord_bot_tutorial.yaml b/pydis_site/apps/resources/resources/vcokltfre_discord_bot_tutorial.yaml index 12f2a154..482cdf91 100644 --- a/pydis_site/apps/resources/resources/vcokltfre_discord_bot_tutorial.yaml +++ b/pydis_site/apps/resources/resources/vcokltfre_discord_bot_tutorial.yaml @@ -2,7 +2,7 @@ description: This tutorial, written by vcokltfre, will walk you through all the aspects of creating your own Discord bot, starting from creating the bot user itself. name: vcokltfre's Discord Bot Tutorial -title_url: https://tutorial.vcokltfre.dev/ +title_url: https://tutorial.vco.sh/ tags: topics: - discord bots |