From 731a3ca4cefd7ed9bc6619b0d98cb0c28f14f290 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Tue, 22 Oct 2019 18:05:09 +0200 Subject: Create an OffensiveMessage model This model will be used to store message that triggered a filter and that will be deleted one week after it was sent. --- .../apps/api/migrations/0046_offensivemessage.py | 25 ++++++++ pydis_site/apps/api/models/__init__.py | 1 + pydis_site/apps/api/models/bot/__init__.py | 1 + .../apps/api/models/bot/offensive_message.py | 44 +++++++++++++++ pydis_site/apps/api/serializers.py | 11 ++++ pydis_site/apps/api/urls.py | 7 ++- pydis_site/apps/api/viewsets/__init__.py | 1 + pydis_site/apps/api/viewsets/bot/__init__.py | 1 + .../apps/api/viewsets/bot/offensive_message.py | 66 ++++++++++++++++++++++ 9 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 pydis_site/apps/api/migrations/0046_offensivemessage.py create mode 100644 pydis_site/apps/api/models/bot/offensive_message.py create mode 100644 pydis_site/apps/api/viewsets/bot/offensive_message.py diff --git a/pydis_site/apps/api/migrations/0046_offensivemessage.py b/pydis_site/apps/api/migrations/0046_offensivemessage.py new file mode 100644 index 00000000..0ce65946 --- /dev/null +++ b/pydis_site/apps/api/migrations/0046_offensivemessage.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.6 on 2019-10-24 17:57 + +import django.core.validators +from django.db import migrations, models +import pydis_site.apps.api.models.bot.offensive_message +import pydis_site.apps.api.models.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0045_add_plural_name_for_log_entry'), + ] + + operations = [ + migrations.CreateModel( + name='OffensiveMessage', + fields=[ + ('id', models.BigIntegerField(help_text='The message ID as taken from Discord.', primary_key=True, serialize=False, validators=[django.core.validators.MinValueValidator(limit_value=0, message='Message IDs cannot be negative.')])), + ('channel_id', models.BigIntegerField(help_text='The channel ID that the message was sent in, taken from Discord.', validators=[django.core.validators.MinValueValidator(limit_value=0, message='Channel IDs cannot be negative.')])), + ('delete_date', models.DateField(help_text='The date on which the message will be auto-deleted.', validators=[pydis_site.apps.api.models.bot.offensive_message.future_date_validator])), + ], + bases=(pydis_site.apps.api.models.utils.ModelReprMixin, models.Model), + ), + ] diff --git a/pydis_site/apps/api/models/__init__.py b/pydis_site/apps/api/models/__init__.py index a4656bc3..450d18cd 100644 --- a/pydis_site/apps/api/models/__init__.py +++ b/pydis_site/apps/api/models/__init__.py @@ -7,6 +7,7 @@ from .bot import ( Message, MessageDeletionContext, Nomination, + OffensiveMessage, OffTopicChannelName, Reminder, Role, diff --git a/pydis_site/apps/api/models/bot/__init__.py b/pydis_site/apps/api/models/bot/__init__.py index 46219ea2..8ae47746 100644 --- a/pydis_site/apps/api/models/bot/__init__.py +++ b/pydis_site/apps/api/models/bot/__init__.py @@ -7,6 +7,7 @@ from .message import Message from .message_deletion_context import MessageDeletionContext from .nomination import Nomination from .off_topic_channel_name import OffTopicChannelName +from .offensive_message import OffensiveMessage from .reminder import Reminder from .role import Role from .tag import Tag diff --git a/pydis_site/apps/api/models/bot/offensive_message.py b/pydis_site/apps/api/models/bot/offensive_message.py new file mode 100644 index 00000000..523fd482 --- /dev/null +++ b/pydis_site/apps/api/models/bot/offensive_message.py @@ -0,0 +1,44 @@ +import datetime + +from django.core.exceptions import ValidationError +from django.core.validators import MinValueValidator +from django.db import models + +from pydis_site.apps.api.models.utils import ModelReprMixin + + +def future_date_validator(date: datetime.date) -> None: + """Raise ValidationError if the date isn't a future date.""" + if date < datetime.date.today(): + raise ValidationError("Date must be a future date") + + +class OffensiveMessage(ModelReprMixin, models.Model): + """A message that triggered a filter and that will be deleted one week after it was sent.""" + + id = models.BigIntegerField( + primary_key=True, + help_text="The message ID as taken from Discord.", + validators=( + MinValueValidator( + limit_value=0, + message="Message IDs cannot be negative." + ), + ) + ) + channel_id = models.BigIntegerField( + help_text=( + "The channel ID that the message was " + "sent in, taken from Discord." + ), + validators=( + MinValueValidator( + limit_value=0, + message="Channel IDs cannot be negative." + ), + ) + ) + delete_date = models.DateField( + help_text="The date on which the message will be auto-deleted.", + validators=(future_date_validator,) + ) diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index 326e20e1..4ef7ec78 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -8,6 +8,7 @@ from .models import ( DocumentationLink, Infraction, LogEntry, MessageDeletionContext, Nomination, OffTopicChannelName, + OffensiveMessage, Reminder, Role, Tag, User ) @@ -236,3 +237,13 @@ class NominationSerializer(ModelSerializer): fields = ( 'id', 'active', 'actor', 'reason', 'user', 'inserted_at', 'end_reason', 'ended_at') + + +class OffensiveMessageSerializer(ModelSerializer): + """A class providing (de-)serialization of `OffensiveMessage` instances.""" + + class Meta: + """Metadata defined for the Django REST Framework.""" + + model = OffensiveMessage + fields = ('id', 'channel_id', 'delete_date') diff --git a/pydis_site/apps/api/urls.py b/pydis_site/apps/api/urls.py index ac6704c8..b1864ba7 100644 --- a/pydis_site/apps/api/urls.py +++ b/pydis_site/apps/api/urls.py @@ -6,7 +6,8 @@ from .viewsets import ( BotSettingViewSet, DeletedMessageViewSet, DocumentationLinkViewSet, InfractionViewSet, LogEntryViewSet, NominationViewSet, - OffTopicChannelNameViewSet, ReminderViewSet, + OffTopicChannelNameViewSet, + OffensiveMessageViewSet, ReminderViewSet, RoleViewSet, TagViewSet, UserViewSet ) @@ -33,6 +34,10 @@ bot_router.register( 'nominations', NominationViewSet ) +bot_router.register( + 'offensive-message', + OffensiveMessageViewSet +) bot_router.register( 'off-topic-channel-names', OffTopicChannelNameViewSet, diff --git a/pydis_site/apps/api/viewsets/__init__.py b/pydis_site/apps/api/viewsets/__init__.py index f9a186d9..3cf9f641 100644 --- a/pydis_site/apps/api/viewsets/__init__.py +++ b/pydis_site/apps/api/viewsets/__init__.py @@ -5,6 +5,7 @@ from .bot import ( DocumentationLinkViewSet, InfractionViewSet, NominationViewSet, + OffensiveMessageViewSet, OffTopicChannelNameViewSet, ReminderViewSet, RoleViewSet, diff --git a/pydis_site/apps/api/viewsets/bot/__init__.py b/pydis_site/apps/api/viewsets/bot/__init__.py index f1851e32..b3e0fa4d 100644 --- a/pydis_site/apps/api/viewsets/bot/__init__.py +++ b/pydis_site/apps/api/viewsets/bot/__init__.py @@ -5,6 +5,7 @@ from .documentation_link import DocumentationLinkViewSet from .infraction import InfractionViewSet from .nomination import NominationViewSet from .off_topic_channel_name import OffTopicChannelNameViewSet +from .offensive_message import OffensiveMessageViewSet from .reminder import ReminderViewSet from .role import RoleViewSet from .tag import TagViewSet diff --git a/pydis_site/apps/api/viewsets/bot/offensive_message.py b/pydis_site/apps/api/viewsets/bot/offensive_message.py new file mode 100644 index 00000000..cd200efe --- /dev/null +++ b/pydis_site/apps/api/viewsets/bot/offensive_message.py @@ -0,0 +1,66 @@ +from django_filters.rest_framework import DjangoFilterBackend +from rest_framework.filters import SearchFilter +from rest_framework.mixins import ( + CreateModelMixin, + DestroyModelMixin, + ListModelMixin, + UpdateModelMixin +) +from rest_framework.viewsets import GenericViewSet + +from pydis_site.apps.api.models.bot.offensive_message import OffensiveMessage +from pydis_site.apps.api.serializers import OffensiveMessageSerializer + + +class OffensiveMessageViewSet( + CreateModelMixin, ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet +): + """ + View providing CRUD access to reminders. + + ## Routes + ### GET /bot/offensive-message + Returns all offensive messages in the database. + + #### Response format + >>> [ + ... { + ... 'id': '631953598091100200', + ... 'channel_id': '291284109232308226', + ... 'delete_date': '2020-01-01' + ... }, + ... ... + ... ] + + #### Status codes + - 200: returned on success + + ### POST /bot/offensive-message + Create a new offensive message object. + + #### Request body + >>> { + ... 'id': int, + ... 'channel_id': int, + ... 'delete_date': datetime.date # ISO-8601-formatted date + ... } + + #### Status codes + - 201: returned on success + - 400: if the body format is invalid + + ### DELETE /bot/offensive-message/ + Delete the offensive message object with the given `id`. + + #### Status codes + - 204: returned on success + - 404: if a offensive message object with the given `id` does not exist + + ## Authentication + Requires an API token. + """ + + serializer_class = OffensiveMessageSerializer + queryset = OffensiveMessage.objects.all() + filter_backends = (DjangoFilterBackend, SearchFilter) + filter_fields = ('delete_date',) -- cgit v1.2.3 From 171aad04e4135fe3c8fdba4db145a29aaba9a96b Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Fri, 25 Oct 2019 13:07:02 +0200 Subject: Write tests for the future date validator --- pydis_site/apps/api/tests/test_validators.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pydis_site/apps/api/tests/test_validators.py b/pydis_site/apps/api/tests/test_validators.py index 4222f0c0..6e86759c 100644 --- a/pydis_site/apps/api/tests/test_validators.py +++ b/pydis_site/apps/api/tests/test_validators.py @@ -1,7 +1,10 @@ +from datetime import date + from django.core.exceptions import ValidationError from django.test import TestCase from ..models.bot.bot_setting import validate_bot_setting_name +from ..models.bot.offensive_message import future_date_validator from ..models.bot.tag import validate_tag_embed @@ -245,3 +248,12 @@ class TagEmbedValidatorTests(TestCase): 'name': "Bob" } }) + + +class OffensiveMessageValidatorsTests(TestCase): + def test_accepts_future_date(self): + future_date_validator(date(3000, 1, 1)) + + def test_rejects_non_future_date(self): + with self.assertRaises(ValidationError): + future_date_validator(date(1000, 1, 1)) -- cgit v1.2.3 From f42c936bddc43b30a8245306c86b859185b5e913 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Fri, 25 Oct 2019 19:16:21 +0200 Subject: Change OffensiveMessage.delete_date from datetime.date to datetime.datetime --- pydis_site/apps/api/models/bot/offensive_message.py | 4 ++-- pydis_site/apps/api/tests/test_validators.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pydis_site/apps/api/models/bot/offensive_message.py b/pydis_site/apps/api/models/bot/offensive_message.py index 523fd482..cee5b32c 100644 --- a/pydis_site/apps/api/models/bot/offensive_message.py +++ b/pydis_site/apps/api/models/bot/offensive_message.py @@ -9,7 +9,7 @@ from pydis_site.apps.api.models.utils import ModelReprMixin def future_date_validator(date: datetime.date) -> None: """Raise ValidationError if the date isn't a future date.""" - if date < datetime.date.today(): + if date < datetime.datetime.utcnow(): raise ValidationError("Date must be a future date") @@ -38,7 +38,7 @@ class OffensiveMessage(ModelReprMixin, models.Model): ), ) ) - delete_date = models.DateField( + delete_date = models.DateTimeField( help_text="The date on which the message will be auto-deleted.", validators=(future_date_validator,) ) diff --git a/pydis_site/apps/api/tests/test_validators.py b/pydis_site/apps/api/tests/test_validators.py index 6e86759c..9d993839 100644 --- a/pydis_site/apps/api/tests/test_validators.py +++ b/pydis_site/apps/api/tests/test_validators.py @@ -1,4 +1,4 @@ -from datetime import date +from datetime import datetime from django.core.exceptions import ValidationError from django.test import TestCase @@ -252,8 +252,8 @@ class TagEmbedValidatorTests(TestCase): class OffensiveMessageValidatorsTests(TestCase): def test_accepts_future_date(self): - future_date_validator(date(3000, 1, 1)) + future_date_validator(datetime(3000, 1, 1)) def test_rejects_non_future_date(self): with self.assertRaises(ValidationError): - future_date_validator(date(1000, 1, 1)) + future_date_validator(datetime(1000, 1, 1)) -- cgit v1.2.3 From 6fac1649252c55b6f12592415de8396349b54686 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Fri, 25 Oct 2019 19:21:24 +0200 Subject: Add merge migration file --- pydis_site/apps/api/migrations/0047_merge_20191025_1920.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 pydis_site/apps/api/migrations/0047_merge_20191025_1920.py diff --git a/pydis_site/apps/api/migrations/0047_merge_20191025_1920.py b/pydis_site/apps/api/migrations/0047_merge_20191025_1920.py new file mode 100644 index 00000000..f70fe24f --- /dev/null +++ b/pydis_site/apps/api/migrations/0047_merge_20191025_1920.py @@ -0,0 +1,14 @@ +# Generated by Django 2.2.6 on 2019-10-25 17:20 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0046_reminder_jump_url'), + ('api', '0046_offensivemessage'), + ] + + operations = [ + ] -- cgit v1.2.3 From 5b291b0708fc78dab439d12e2ddbcfb6cb718bbf Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Fri, 25 Oct 2019 19:22:14 +0200 Subject: Add migartion file for OffensiveMssage.delete_date --- .../apps/api/migrations/0048_auto_20191025_1921.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 pydis_site/apps/api/migrations/0048_auto_20191025_1921.py diff --git a/pydis_site/apps/api/migrations/0048_auto_20191025_1921.py b/pydis_site/apps/api/migrations/0048_auto_20191025_1921.py new file mode 100644 index 00000000..2e5e670a --- /dev/null +++ b/pydis_site/apps/api/migrations/0048_auto_20191025_1921.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.6 on 2019-10-25 17:21 + +from django.db import migrations, models +import pydis_site.apps.api.models.bot.offensive_message + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0047_merge_20191025_1920'), + ] + + operations = [ + migrations.AlterField( + model_name='offensivemessage', + name='delete_date', + field=models.DateTimeField(help_text='The date on which the message will be auto-deleted.', validators=[pydis_site.apps.api.models.bot.offensive_message.future_date_validator]), + ), + ] -- cgit v1.2.3 From 6334fd1d7e57f39ed61c90d2bace6b367b676d2f Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Fri, 25 Oct 2019 23:36:31 +0200 Subject: Fix type error in the future date validator --- pydis_site/apps/api/models/bot/offensive_message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/apps/api/models/bot/offensive_message.py b/pydis_site/apps/api/models/bot/offensive_message.py index cee5b32c..c4080c1f 100644 --- a/pydis_site/apps/api/models/bot/offensive_message.py +++ b/pydis_site/apps/api/models/bot/offensive_message.py @@ -9,7 +9,7 @@ from pydis_site.apps.api.models.utils import ModelReprMixin def future_date_validator(date: datetime.date) -> None: """Raise ValidationError if the date isn't a future date.""" - if date < datetime.datetime.utcnow(): + if date < datetime.datetime.now(datetime.timezone.utc): raise ValidationError("Date must be a future date") -- cgit v1.2.3 From c727d4ce14ae94f0b60402c603e4129a8efe6ef8 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sat, 26 Oct 2019 11:14:55 +0200 Subject: Add the offensive message model to the admin panel --- pydis_site/apps/api/admin.py | 2 ++ pydis_site/apps/api/models/bot/offensive_message.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/pydis_site/apps/api/admin.py b/pydis_site/apps/api/admin.py index 059f52eb..0333fefc 100644 --- a/pydis_site/apps/api/admin.py +++ b/pydis_site/apps/api/admin.py @@ -12,6 +12,7 @@ from .models import ( MessageDeletionContext, Nomination, OffTopicChannelName, + OffensiveMessage, Role, Tag, User @@ -60,6 +61,7 @@ admin.site.register(Infraction) admin.site.register(LogEntry, LogEntryAdmin) admin.site.register(MessageDeletionContext) admin.site.register(Nomination) +admin.site.register(OffensiveMessage) admin.site.register(OffTopicChannelName) admin.site.register(Role) admin.site.register(Tag) diff --git a/pydis_site/apps/api/models/bot/offensive_message.py b/pydis_site/apps/api/models/bot/offensive_message.py index c4080c1f..b466d9c2 100644 --- a/pydis_site/apps/api/models/bot/offensive_message.py +++ b/pydis_site/apps/api/models/bot/offensive_message.py @@ -42,3 +42,7 @@ class OffensiveMessage(ModelReprMixin, models.Model): help_text="The date on which the message will be auto-deleted.", validators=(future_date_validator,) ) + + def __str__(self): + """Return some info on this message, for display purposes only.""" + return f"Message {self.id}, will be deleted at {self.delete_date}" -- cgit v1.2.3 From e19d310eb03efa5b576b523649c0d6df761f5325 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sat, 26 Oct 2019 11:19:15 +0200 Subject: Change docs to use datetime.datetime instead of datetime.date --- pydis_site/apps/api/viewsets/bot/offensive_message.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pydis_site/apps/api/viewsets/bot/offensive_message.py b/pydis_site/apps/api/viewsets/bot/offensive_message.py index cd200efe..380234dd 100644 --- a/pydis_site/apps/api/viewsets/bot/offensive_message.py +++ b/pydis_site/apps/api/viewsets/bot/offensive_message.py @@ -27,7 +27,7 @@ class OffensiveMessageViewSet( ... { ... 'id': '631953598091100200', ... 'channel_id': '291284109232308226', - ... 'delete_date': '2020-01-01' + ... 'delete_date': '2019-11-01T21:51:15.545000Z' ... }, ... ... ... ] @@ -42,7 +42,7 @@ class OffensiveMessageViewSet( >>> { ... 'id': int, ... 'channel_id': int, - ... 'delete_date': datetime.date # ISO-8601-formatted date + ... 'delete_date': datetime.datetime # ISO-8601-formatted date ... } #### Status codes -- cgit v1.2.3 From 981ae74578862ef24d03947eb368d19c9057461e Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sat, 26 Oct 2019 11:33:14 +0200 Subject: Delete unnecessary search filter --- pydis_site/apps/api/viewsets/bot/offensive_message.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pydis_site/apps/api/viewsets/bot/offensive_message.py b/pydis_site/apps/api/viewsets/bot/offensive_message.py index 380234dd..0ef5666b 100644 --- a/pydis_site/apps/api/viewsets/bot/offensive_message.py +++ b/pydis_site/apps/api/viewsets/bot/offensive_message.py @@ -1,5 +1,3 @@ -from django_filters.rest_framework import DjangoFilterBackend -from rest_framework.filters import SearchFilter from rest_framework.mixins import ( CreateModelMixin, DestroyModelMixin, @@ -62,5 +60,3 @@ class OffensiveMessageViewSet( serializer_class = OffensiveMessageSerializer queryset = OffensiveMessage.objects.all() - filter_backends = (DjangoFilterBackend, SearchFilter) - filter_fields = ('delete_date',) -- cgit v1.2.3 From 57992886c53977fca7b3034d648a94cf4b4d4df1 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sat, 26 Oct 2019 17:03:57 +0200 Subject: Write tests for the offensive message model. --- pydis_site/apps/api/tests/test_models.py | 6 +++ .../apps/api/tests/test_offensive_message.py | 61 ++++++++++++++++++++++ pydis_site/apps/api/tests/test_validators.py | 6 +-- 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 pydis_site/apps/api/tests/test_offensive_message.py diff --git a/pydis_site/apps/api/tests/test_models.py b/pydis_site/apps/api/tests/test_models.py index b4a766d0..a97d3251 100644 --- a/pydis_site/apps/api/tests/test_models.py +++ b/pydis_site/apps/api/tests/test_models.py @@ -12,6 +12,7 @@ from ..models import ( ModelReprMixin, Nomination, OffTopicChannelName, + OffensiveMessage, Reminder, Role, Tag, @@ -69,6 +70,11 @@ class StringDunderMethodTests(SimpleTestCase): DocumentationLink( 'test', 'http://example.com', 'http://example.com' ), + OffensiveMessage( + id=602951077675139072, + channel_id=291284109232308226, + delete_date=dt(3000, 1, 1) + ), OffTopicChannelName(name='bob-the-builders-playground'), Role( id=5, name='test role', diff --git a/pydis_site/apps/api/tests/test_offensive_message.py b/pydis_site/apps/api/tests/test_offensive_message.py new file mode 100644 index 00000000..4ef9201e --- /dev/null +++ b/pydis_site/apps/api/tests/test_offensive_message.py @@ -0,0 +1,61 @@ +import datetime + +from django_hosts.resolvers import reverse + +from .base import APISubdomainTestCase +from ..models import OffensiveMessage + + +class CreationTests(APISubdomainTestCase): + def test_accept_valid_data(self): + url = reverse('bot:offensivemessage-list', host='api') + delete_at = datetime.datetime.now() + datetime.timedelta(days=1) + data = { + 'id': '602951077675139072', + 'channel_id': '291284109232308226', + 'delete_date': delete_at.isoformat()[:-1] + } + + aware_delete_at = delete_at.replace(tzinfo=datetime.timezone.utc) + + response = self.client.post(url, data=data) + self.assertEqual(response.status_code, 201) + + offensive_message = OffensiveMessage.objects.get(id=response.json()['id']) + self.assertAlmostEqual( + aware_delete_at, + offensive_message.delete_date, + delta=datetime.timedelta(seconds=1) + ) + self.assertEqual(data['id'], str(offensive_message.id)) + self.assertEqual(data['channel_id'], str(offensive_message.channel_id)) + + def test_returns_400_on_non_future_date(self): + url = reverse('bot:offensivemessage-list', host='api') + delete_at = datetime.datetime.now() - datetime.timedelta(days=1) + data = { + 'id': '602951077675139072', + 'channel_id': '291284109232308226', + 'delete_date': delete_at.isoformat()[:-1] + } + response = self.client.post(url, data=data) + self.assertEqual(response.status_code, 400) + + def test_returns_400_on_negative_id_or_channel_id(self): + url = reverse('bot:offensivemessage-list', host='api') + delete_at = datetime.datetime.now() + datetime.timedelta(days=1) + data = { + 'id': '-602951077675139072', + 'channel_id': '291284109232308226', + 'delete_date': delete_at.isoformat()[:-1] + } + response = self.client.post(url, data=data) + self.assertEqual(response.status_code, 400) + + data = { + 'id': '602951077675139072', + 'channel_id': '-291284109232308226', + 'delete_date': delete_at.isoformat()[:-1] + } + response = self.client.post(url, data=data) + self.assertEqual(response.status_code, 400) diff --git a/pydis_site/apps/api/tests/test_validators.py b/pydis_site/apps/api/tests/test_validators.py index 9d993839..241af08c 100644 --- a/pydis_site/apps/api/tests/test_validators.py +++ b/pydis_site/apps/api/tests/test_validators.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone from django.core.exceptions import ValidationError from django.test import TestCase @@ -252,8 +252,8 @@ class TagEmbedValidatorTests(TestCase): class OffensiveMessageValidatorsTests(TestCase): def test_accepts_future_date(self): - future_date_validator(datetime(3000, 1, 1)) + future_date_validator(datetime(3000, 1, 1, tzinfo=timezone.utc)) def test_rejects_non_future_date(self): with self.assertRaises(ValidationError): - future_date_validator(datetime(1000, 1, 1)) + future_date_validator(datetime(1000, 1, 1, tzinfo=timezone.utc)) -- cgit v1.2.3 From ee3f4f937c99ef3db92afc2fcba746003ec694f0 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Mon, 28 Oct 2019 18:20:07 +0100 Subject: Add a attachments field to the message model --- pydis_site/apps/api/models/bot/message.py | 6 ++++++ pydis_site/apps/api/serializers.py | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pydis_site/apps/api/models/bot/message.py b/pydis_site/apps/api/models/bot/message.py index 31316a01..72b0b61a 100644 --- a/pydis_site/apps/api/models/bot/message.py +++ b/pydis_site/apps/api/models/bot/message.py @@ -51,6 +51,12 @@ class Message(ModelReprMixin, models.Model): ), help_text="Embeds attached to this message." ) + attachments = pgfields.ArrayField( + models.URLField( + max_length=512 + ), + help_text="Attachments attached to this message." + ) @property def timestamp(self) -> datetime: diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index 8a605612..e091ff4f 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -49,7 +49,8 @@ class DeletedMessageSerializer(ModelSerializer): fields = ( 'id', 'author', 'channel_id', 'content', - 'embeds', 'deletion_context' + 'embeds', 'deletion_context', + 'attachments' ) -- cgit v1.2.3 From 541850858cb1fe7da61fa94ed4f8d3e0f787e3a7 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Mon, 28 Oct 2019 18:22:00 +0100 Subject: Add migration for message.attachments --- .../migrations/0047_deletedmessage_attachments.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py diff --git a/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py b/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py new file mode 100644 index 00000000..a738faff --- /dev/null +++ b/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.6 on 2019-10-28 17:12 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0046_reminder_jump_url'), + ] + + operations = [ + migrations.AddField( + model_name='deletedmessage', + name='attachments', + field=django.contrib.postgres.fields.ArrayField(base_field=models.URLField(max_length=512), default=[], help_text='Attachments attached to this message.', size=None), + preserve_default=False, + ), + ] -- cgit v1.2.3 From 803331562bcc8bf5b09b2a7e9fcfbe00e8796ea9 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Mon, 28 Oct 2019 18:23:47 +0100 Subject: Show attachments in staff logs --- pydis_site/templates/staff/logs.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pydis_site/templates/staff/logs.html b/pydis_site/templates/staff/logs.html index 9c8ed7d3..a0bfa2a7 100644 --- a/pydis_site/templates/staff/logs.html +++ b/pydis_site/templates/staff/logs.html @@ -24,6 +24,11 @@
{{ message.content|linebreaks }}
+
+ {% for attachment in message.attachments %} + Attachment + {% endfor %} +
{% for embed in message.embeds %}
-- cgit v1.2.3 From 14cde62b4d8358032f1b1f706250efaaf9c646ea Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Mon, 28 Oct 2019 18:50:23 +0100 Subject: Write tests for message.attachments --- pydis_site/apps/api/tests/test_deleted_messages.py | 9 ++++++--- pydis_site/apps/staff/tests/test_logs_view.py | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pydis_site/apps/api/tests/test_deleted_messages.py b/pydis_site/apps/api/tests/test_deleted_messages.py index d1e9f2f5..b3a8197b 100644 --- a/pydis_site/apps/api/tests/test_deleted_messages.py +++ b/pydis_site/apps/api/tests/test_deleted_messages.py @@ -25,14 +25,16 @@ class DeletedMessagesWithoutActorTests(APISubdomainTestCase): 'id': 55, 'channel_id': 5555, 'content': "Terror Billy is a meanie", - 'embeds': [] + 'embeds': [], + 'attachments': [] }, { 'author': cls.author.id, 'id': 56, 'channel_id': 5555, 'content': "If you purge this, you're evil", - 'embeds': [] + 'embeds': [], + 'attachments': [] } ] } @@ -64,7 +66,8 @@ class DeletedMessagesWithActorTests(APISubdomainTestCase): 'id': 12903, 'channel_id': 1824, 'content': "I hate trailing commas", - 'embeds': [] + 'embeds': [], + 'attachments': [] }, ] } diff --git a/pydis_site/apps/staff/tests/test_logs_view.py b/pydis_site/apps/staff/tests/test_logs_view.py index 32cb6bbf..b01e3f3e 100644 --- a/pydis_site/apps/staff/tests/test_logs_view.py +++ b/pydis_site/apps/staff/tests/test_logs_view.py @@ -37,6 +37,7 @@ class TestLogsView(TestCase): channel_id=1984, content='I think my tape has run out...', embeds=[], + attachments=[], deletion_context=cls.deletion_context, ) @@ -101,6 +102,7 @@ class TestLogsView(TestCase): channel_id=1984, content='Does that mean this thing will halt?', embeds=[cls.embed_one, cls.embed_two], + attachments=['https://http.cat/100', 'https://http.cat/402'], deletion_context=cls.deletion_context, ) -- cgit v1.2.3 From 904edb20f694c40435ba27f5a96f759dbf87f3e3 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 31 Oct 2019 13:16:15 +0100 Subject: Allow empty attachment field --- .../api/migrations/0048_alter_deletedmessage_api.py | 19 +++++++++++++++++++ pydis_site/apps/api/models/bot/message.py | 1 + 2 files changed, 20 insertions(+) create mode 100644 pydis_site/apps/api/migrations/0048_alter_deletedmessage_api.py diff --git a/pydis_site/apps/api/migrations/0048_alter_deletedmessage_api.py b/pydis_site/apps/api/migrations/0048_alter_deletedmessage_api.py new file mode 100644 index 00000000..364f57b1 --- /dev/null +++ b/pydis_site/apps/api/migrations/0048_alter_deletedmessage_api.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.6 on 2019-10-31 12:14 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0047_deletedmessage_attachments'), + ] + + operations = [ + migrations.AlterField( + model_name='deletedmessage', + name='attachments', + field=django.contrib.postgres.fields.ArrayField(base_field=models.URLField(max_length=512), blank=True, help_text='Attachments attached to this message.', size=None), + ), + ] diff --git a/pydis_site/apps/api/models/bot/message.py b/pydis_site/apps/api/models/bot/message.py index 72b0b61a..8b18fc9f 100644 --- a/pydis_site/apps/api/models/bot/message.py +++ b/pydis_site/apps/api/models/bot/message.py @@ -55,6 +55,7 @@ class Message(ModelReprMixin, models.Model): models.URLField( max_length=512 ), + blank=True, help_text="Attachments attached to this message." ) -- cgit v1.2.3 From ec1c0f26bfbd7f2b3769ab37e02c3d31b3f16b4c Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Thu, 7 Nov 2019 18:55:59 +0100 Subject: Squash down migration files --- .../apps/api/migrations/0046_offensivemessage.py | 25 ---------------------- .../api/migrations/0047_merge_20191025_1920.py | 14 ------------ .../apps/api/migrations/0047_offensivemessage.py | 25 ++++++++++++++++++++++ .../apps/api/migrations/0048_auto_20191025_1921.py | 19 ---------------- 4 files changed, 25 insertions(+), 58 deletions(-) delete mode 100644 pydis_site/apps/api/migrations/0046_offensivemessage.py delete mode 100644 pydis_site/apps/api/migrations/0047_merge_20191025_1920.py create mode 100644 pydis_site/apps/api/migrations/0047_offensivemessage.py delete mode 100644 pydis_site/apps/api/migrations/0048_auto_20191025_1921.py diff --git a/pydis_site/apps/api/migrations/0046_offensivemessage.py b/pydis_site/apps/api/migrations/0046_offensivemessage.py deleted file mode 100644 index 0ce65946..00000000 --- a/pydis_site/apps/api/migrations/0046_offensivemessage.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 2.2.6 on 2019-10-24 17:57 - -import django.core.validators -from django.db import migrations, models -import pydis_site.apps.api.models.bot.offensive_message -import pydis_site.apps.api.models.utils - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0045_add_plural_name_for_log_entry'), - ] - - operations = [ - migrations.CreateModel( - name='OffensiveMessage', - fields=[ - ('id', models.BigIntegerField(help_text='The message ID as taken from Discord.', primary_key=True, serialize=False, validators=[django.core.validators.MinValueValidator(limit_value=0, message='Message IDs cannot be negative.')])), - ('channel_id', models.BigIntegerField(help_text='The channel ID that the message was sent in, taken from Discord.', validators=[django.core.validators.MinValueValidator(limit_value=0, message='Channel IDs cannot be negative.')])), - ('delete_date', models.DateField(help_text='The date on which the message will be auto-deleted.', validators=[pydis_site.apps.api.models.bot.offensive_message.future_date_validator])), - ], - bases=(pydis_site.apps.api.models.utils.ModelReprMixin, models.Model), - ), - ] diff --git a/pydis_site/apps/api/migrations/0047_merge_20191025_1920.py b/pydis_site/apps/api/migrations/0047_merge_20191025_1920.py deleted file mode 100644 index f70fe24f..00000000 --- a/pydis_site/apps/api/migrations/0047_merge_20191025_1920.py +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by Django 2.2.6 on 2019-10-25 17:20 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0046_reminder_jump_url'), - ('api', '0046_offensivemessage'), - ] - - operations = [ - ] diff --git a/pydis_site/apps/api/migrations/0047_offensivemessage.py b/pydis_site/apps/api/migrations/0047_offensivemessage.py new file mode 100644 index 00000000..f2068c1b --- /dev/null +++ b/pydis_site/apps/api/migrations/0047_offensivemessage.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.6 on 2019-11-07 17:55 + +import django.core.validators +from django.db import migrations, models +import pydis_site.apps.api.models.bot.offensive_message +import pydis_site.apps.api.models.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0046_reminder_jump_url'), + ] + + operations = [ + migrations.CreateModel( + name='OffensiveMessage', + fields=[ + ('id', models.BigIntegerField(help_text='The message ID as taken from Discord.', primary_key=True, serialize=False, validators=[django.core.validators.MinValueValidator(limit_value=0, message='Message IDs cannot be negative.')])), + ('channel_id', models.BigIntegerField(help_text='The channel ID that the message was sent in, taken from Discord.', validators=[django.core.validators.MinValueValidator(limit_value=0, message='Channel IDs cannot be negative.')])), + ('delete_date', models.DateTimeField(help_text='The date on which the message will be auto-deleted.', validators=[pydis_site.apps.api.models.bot.offensive_message.future_date_validator])), + ], + bases=(pydis_site.apps.api.models.utils.ModelReprMixin, models.Model), + ), + ] diff --git a/pydis_site/apps/api/migrations/0048_auto_20191025_1921.py b/pydis_site/apps/api/migrations/0048_auto_20191025_1921.py deleted file mode 100644 index 2e5e670a..00000000 --- a/pydis_site/apps/api/migrations/0048_auto_20191025_1921.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2.6 on 2019-10-25 17:21 - -from django.db import migrations, models -import pydis_site.apps.api.models.bot.offensive_message - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0047_merge_20191025_1920'), - ] - - operations = [ - migrations.AlterField( - model_name='offensivemessage', - name='delete_date', - field=models.DateTimeField(help_text='The date on which the message will be auto-deleted.', validators=[pydis_site.apps.api.models.bot.offensive_message.future_date_validator]), - ), - ] -- cgit v1.2.3 From a33af9d6d356fa416863e487f71aae4ba0977a0f Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Thu, 7 Nov 2019 18:59:47 +0100 Subject: Fix copy pasting mistake --- pydis_site/apps/api/viewsets/bot/offensive_message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/apps/api/viewsets/bot/offensive_message.py b/pydis_site/apps/api/viewsets/bot/offensive_message.py index 0ef5666b..371bd8e7 100644 --- a/pydis_site/apps/api/viewsets/bot/offensive_message.py +++ b/pydis_site/apps/api/viewsets/bot/offensive_message.py @@ -14,7 +14,7 @@ class OffensiveMessageViewSet( CreateModelMixin, ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet ): """ - View providing CRUD access to reminders. + View providing CRUD access to offensive messages. ## Routes ### GET /bot/offensive-message -- cgit v1.2.3 From edaf17636ac9ccf832136ed54d00f0a5038d9d7b Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Thu, 7 Nov 2019 19:02:19 +0100 Subject: Block PATCH and PUT methods --- pydis_site/apps/api/viewsets/bot/offensive_message.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pydis_site/apps/api/viewsets/bot/offensive_message.py b/pydis_site/apps/api/viewsets/bot/offensive_message.py index 371bd8e7..f25c14b4 100644 --- a/pydis_site/apps/api/viewsets/bot/offensive_message.py +++ b/pydis_site/apps/api/viewsets/bot/offensive_message.py @@ -1,8 +1,7 @@ from rest_framework.mixins import ( CreateModelMixin, DestroyModelMixin, - ListModelMixin, - UpdateModelMixin + ListModelMixin ) from rest_framework.viewsets import GenericViewSet @@ -11,7 +10,7 @@ from pydis_site.apps.api.serializers import OffensiveMessageSerializer class OffensiveMessageViewSet( - CreateModelMixin, ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet + CreateModelMixin, ListModelMixin, DestroyModelMixin, GenericViewSet ): """ View providing CRUD access to offensive messages. -- cgit v1.2.3 From f06148f6efb89e85a8dfad60cce21d5f6b95d505 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Thu, 7 Nov 2019 19:09:53 +0100 Subject: Merge master migration files --- .../apps/api/migrations/0047_offensivemessage.py | 25 ---------------------- .../apps/api/migrations/0049_offensivemessage.py | 25 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 25 deletions(-) delete mode 100644 pydis_site/apps/api/migrations/0047_offensivemessage.py create mode 100644 pydis_site/apps/api/migrations/0049_offensivemessage.py diff --git a/pydis_site/apps/api/migrations/0047_offensivemessage.py b/pydis_site/apps/api/migrations/0047_offensivemessage.py deleted file mode 100644 index f2068c1b..00000000 --- a/pydis_site/apps/api/migrations/0047_offensivemessage.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 2.2.6 on 2019-11-07 17:55 - -import django.core.validators -from django.db import migrations, models -import pydis_site.apps.api.models.bot.offensive_message -import pydis_site.apps.api.models.utils - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0046_reminder_jump_url'), - ] - - operations = [ - migrations.CreateModel( - name='OffensiveMessage', - fields=[ - ('id', models.BigIntegerField(help_text='The message ID as taken from Discord.', primary_key=True, serialize=False, validators=[django.core.validators.MinValueValidator(limit_value=0, message='Message IDs cannot be negative.')])), - ('channel_id', models.BigIntegerField(help_text='The channel ID that the message was sent in, taken from Discord.', validators=[django.core.validators.MinValueValidator(limit_value=0, message='Channel IDs cannot be negative.')])), - ('delete_date', models.DateTimeField(help_text='The date on which the message will be auto-deleted.', validators=[pydis_site.apps.api.models.bot.offensive_message.future_date_validator])), - ], - bases=(pydis_site.apps.api.models.utils.ModelReprMixin, models.Model), - ), - ] diff --git a/pydis_site/apps/api/migrations/0049_offensivemessage.py b/pydis_site/apps/api/migrations/0049_offensivemessage.py new file mode 100644 index 00000000..fe4a1961 --- /dev/null +++ b/pydis_site/apps/api/migrations/0049_offensivemessage.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.6 on 2019-11-07 18:08 + +import django.core.validators +from django.db import migrations, models +import pydis_site.apps.api.models.bot.offensive_message +import pydis_site.apps.api.models.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0048_add_infractions_unique_constraints_active'), + ] + + operations = [ + migrations.CreateModel( + name='OffensiveMessage', + fields=[ + ('id', models.BigIntegerField(help_text='The message ID as taken from Discord.', primary_key=True, serialize=False, validators=[django.core.validators.MinValueValidator(limit_value=0, message='Message IDs cannot be negative.')])), + ('channel_id', models.BigIntegerField(help_text='The channel ID that the message was sent in, taken from Discord.', validators=[django.core.validators.MinValueValidator(limit_value=0, message='Channel IDs cannot be negative.')])), + ('delete_date', models.DateTimeField(help_text='The date on which the message will be auto-deleted.', validators=[pydis_site.apps.api.models.bot.offensive_message.future_date_validator])), + ], + bases=(pydis_site.apps.api.models.utils.ModelReprMixin, models.Model), + ), + ] -- cgit v1.2.3 From 1acf84b47eda889df5c14caba3ebc38bb13ab542 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sun, 10 Nov 2019 18:30:28 +0100 Subject: Make sure the API return the appropriate response. --- pydis_site/apps/api/tests/test_offensive_message.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pydis_site/apps/api/tests/test_offensive_message.py b/pydis_site/apps/api/tests/test_offensive_message.py index 4ef9201e..dd9aaf21 100644 --- a/pydis_site/apps/api/tests/test_offensive_message.py +++ b/pydis_site/apps/api/tests/test_offensive_message.py @@ -40,6 +40,9 @@ class CreationTests(APISubdomainTestCase): } response = self.client.post(url, data=data) self.assertEqual(response.status_code, 400) + self.assertEqual(response.json(), { + 'delete_date': ['Date must be a future date'] + }) def test_returns_400_on_negative_id_or_channel_id(self): url = reverse('bot:offensivemessage-list', host='api') @@ -51,6 +54,9 @@ class CreationTests(APISubdomainTestCase): } response = self.client.post(url, data=data) self.assertEqual(response.status_code, 400) + self.assertEqual(response.json(), { + 'id': ['Ensure this value is greater than or equal to 0.'] + }) data = { 'id': '602951077675139072', @@ -59,3 +65,6 @@ class CreationTests(APISubdomainTestCase): } response = self.client.post(url, data=data) self.assertEqual(response.status_code, 400) + self.assertEqual(response.json(), { + 'channel_id': ['Ensure this value is greater than or equal to 0.'] + }) -- cgit v1.2.3 From 3e01ca7c15aa50683b9d91e427bd8a42a7516ad7 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Mon, 11 Nov 2019 17:48:42 +0100 Subject: Add tests to make sure the view return 405 for PATCH and PUT requests --- .../apps/api/tests/test_offensive_message.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pydis_site/apps/api/tests/test_offensive_message.py b/pydis_site/apps/api/tests/test_offensive_message.py index dd9aaf21..0c3ba4f6 100644 --- a/pydis_site/apps/api/tests/test_offensive_message.py +++ b/pydis_site/apps/api/tests/test_offensive_message.py @@ -68,3 +68,25 @@ class CreationTests(APISubdomainTestCase): self.assertEqual(response.json(), { 'channel_id': ['Ensure this value is greater than or equal to 0.'] }) + + +class NotAllowedMethodsTests(APISubdomainTestCase): + @classmethod + def setUpTestData(cls): # noqa + delete_at = datetime.datetime.now() + datetime.timedelta(days=1) + + cls.valid_offensive_message = OffensiveMessage.objects.create( + id=602951077675139072, + channel_id=291284109232308226, + delete_date=delete_at.isoformat()[:-1] + ) + + def test_returns_405_for_patch_and_put_requests(self): + url = reverse( + 'bot:offensivemessage-detail', host='api', args=(self.valid_offensive_message.id,) + ) + + response = self.client.patch(url, {}) + self.assertEqual(response.status_code, 405) + response = self.client.put(url, {}) + self.assertEqual(response.status_code, 405) -- cgit v1.2.3 From 20bfc996404ec9faee8c7105001540724a197dac Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Mon, 11 Nov 2019 18:01:55 +0100 Subject: Add deletion tests --- .../apps/api/tests/test_offensive_message.py | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/pydis_site/apps/api/tests/test_offensive_message.py b/pydis_site/apps/api/tests/test_offensive_message.py index 0c3ba4f6..04da6d26 100644 --- a/pydis_site/apps/api/tests/test_offensive_message.py +++ b/pydis_site/apps/api/tests/test_offensive_message.py @@ -70,6 +70,30 @@ class CreationTests(APISubdomainTestCase): }) +class DeletionTests(APISubdomainTestCase): + @classmethod + def setUpTestData(cls): # noqa + delete_at = datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(days=1) + + cls.valid_offensive_message = OffensiveMessage.objects.create( + id=602951077675139072, + channel_id=291284109232308226, + delete_date=delete_at.isoformat() + ) + + def test_delete_data(self): + url = reverse( + 'bot:offensivemessage-detail', host='api', args=(self.valid_offensive_message.id,) + ) + + response = self.client.delete(url) + self.assertEqual(response.status_code, 204) + + url = reverse('bot:offensivemessage-list', host='api') + response = self.client.get(url) + self.assertNotIn(self.valid_offensive_message.id, response.json()) + + class NotAllowedMethodsTests(APISubdomainTestCase): @classmethod def setUpTestData(cls): # noqa -- cgit v1.2.3 From 5792c4f43c09430275ce9223704072635de083fc Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Mon, 11 Nov 2019 18:02:41 +0100 Subject: Change setUpTestData to use aware datetime This remove a warning during test run --- pydis_site/apps/api/tests/test_offensive_message.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pydis_site/apps/api/tests/test_offensive_message.py b/pydis_site/apps/api/tests/test_offensive_message.py index 04da6d26..a80b1793 100644 --- a/pydis_site/apps/api/tests/test_offensive_message.py +++ b/pydis_site/apps/api/tests/test_offensive_message.py @@ -97,12 +97,12 @@ class DeletionTests(APISubdomainTestCase): class NotAllowedMethodsTests(APISubdomainTestCase): @classmethod def setUpTestData(cls): # noqa - delete_at = datetime.datetime.now() + datetime.timedelta(days=1) + delete_at = datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(days=1) cls.valid_offensive_message = OffensiveMessage.objects.create( id=602951077675139072, channel_id=291284109232308226, - delete_date=delete_at.isoformat()[:-1] + delete_date=delete_at.isoformat() ) def test_returns_405_for_patch_and_put_requests(self): -- cgit v1.2.3 From 21961b6d002bac5b35641505bd9f91902da46047 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Tue, 12 Nov 2019 11:35:42 +0100 Subject: Make use of subtests Co-authored-by: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> --- .../apps/api/tests/test_offensive_message.py | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/pydis_site/apps/api/tests/test_offensive_message.py b/pydis_site/apps/api/tests/test_offensive_message.py index a80b1793..a270074b 100644 --- a/pydis_site/apps/api/tests/test_offensive_message.py +++ b/pydis_site/apps/api/tests/test_offensive_message.py @@ -48,26 +48,25 @@ class CreationTests(APISubdomainTestCase): url = reverse('bot:offensivemessage-list', host='api') delete_at = datetime.datetime.now() + datetime.timedelta(days=1) data = { - 'id': '-602951077675139072', + 'id': '602951077675139072', 'channel_id': '291284109232308226', 'delete_date': delete_at.isoformat()[:-1] } - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'id': ['Ensure this value is greater than or equal to 0.'] - }) + cases = ( + ('id', '-602951077675139072'), + ('channel_id', '-291284109232308226') + ) - data = { - 'id': '602951077675139072', - 'channel_id': '-291284109232308226', - 'delete_date': delete_at.isoformat()[:-1] - } - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'channel_id': ['Ensure this value is greater than or equal to 0.'] - }) + for field, invalid_value in cases: + with self.subTest(fied=field, invalid_value=invalid_value): + test_data = data.copy() + test_data.update({field: invalid_value}) + + response = self.client.post(url, test_data) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json(), { + field: ['Ensure this value is greater than or equal to 0.'] + }) class DeletionTests(APISubdomainTestCase): @@ -109,8 +108,9 @@ class NotAllowedMethodsTests(APISubdomainTestCase): url = reverse( 'bot:offensivemessage-detail', host='api', args=(self.valid_offensive_message.id,) ) + not_allowed_methods = (self.client.patch, self.client.put) - response = self.client.patch(url, {}) - self.assertEqual(response.status_code, 405) - response = self.client.put(url, {}) - self.assertEqual(response.status_code, 405) + for method in not_allowed_methods: + with self.subTest(method=method): + response = method(url, {}) + self.assertEqual(response.status_code, 405) -- cgit v1.2.3 From 80c5799cb3538dcfff48b2f9f017097abb65ab72 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Fri, 15 Nov 2019 10:04:29 +0100 Subject: Allow blank attachment field --- pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py b/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py index a738faff..f335e003 100644 --- a/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py +++ b/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py @@ -14,7 +14,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='deletedmessage', name='attachments', - field=django.contrib.postgres.fields.ArrayField(base_field=models.URLField(max_length=512), default=[], help_text='Attachments attached to this message.', size=None), + field=django.contrib.postgres.fields.ArrayField(base_field=models.URLField(max_length=512), default=[], blank=True, help_text='Attachments attached to this message.', size=None), preserve_default=False, ), ] -- cgit v1.2.3 From 912ecffab9797fa86ed90590438de3bd1211f2c8 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Fri, 15 Nov 2019 10:05:02 +0100 Subject: Delete useless migration file --- .../api/migrations/0048_alter_deletedmessage_api.py | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 pydis_site/apps/api/migrations/0048_alter_deletedmessage_api.py diff --git a/pydis_site/apps/api/migrations/0048_alter_deletedmessage_api.py b/pydis_site/apps/api/migrations/0048_alter_deletedmessage_api.py deleted file mode 100644 index 364f57b1..00000000 --- a/pydis_site/apps/api/migrations/0048_alter_deletedmessage_api.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2.6 on 2019-10-31 12:14 - -import django.contrib.postgres.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0047_deletedmessage_attachments'), - ] - - operations = [ - migrations.AlterField( - model_name='deletedmessage', - name='attachments', - field=django.contrib.postgres.fields.ArrayField(base_field=models.URLField(max_length=512), blank=True, help_text='Attachments attached to this message.', size=None), - ), - ] -- cgit v1.2.3 From 4b58cf53a7931ab0b3091266afa6e15dd0b985a0 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Fri, 15 Nov 2019 10:16:49 +0100 Subject: Update migration history --- .../migrations/0047_deletedmessage_attachments.py | 20 -------------------- .../migrations/0049_deletedmessage_attachments.py | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 20 deletions(-) delete mode 100644 pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py create mode 100644 pydis_site/apps/api/migrations/0049_deletedmessage_attachments.py diff --git a/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py b/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py deleted file mode 100644 index f335e003..00000000 --- a/pydis_site/apps/api/migrations/0047_deletedmessage_attachments.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.2.6 on 2019-10-28 17:12 - -import django.contrib.postgres.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0046_reminder_jump_url'), - ] - - operations = [ - migrations.AddField( - model_name='deletedmessage', - name='attachments', - field=django.contrib.postgres.fields.ArrayField(base_field=models.URLField(max_length=512), default=[], blank=True, help_text='Attachments attached to this message.', size=None), - preserve_default=False, - ), - ] diff --git a/pydis_site/apps/api/migrations/0049_deletedmessage_attachments.py b/pydis_site/apps/api/migrations/0049_deletedmessage_attachments.py new file mode 100644 index 00000000..9cbde96d --- /dev/null +++ b/pydis_site/apps/api/migrations/0049_deletedmessage_attachments.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.6 on 2019-10-28 17:12 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0048_add_infractions_unique_constraints_active'), + ] + + operations = [ + migrations.AddField( + model_name='deletedmessage', + name='attachments', + field=django.contrib.postgres.fields.ArrayField(base_field=models.URLField(max_length=512), default=[], blank=True, help_text='Attachments attached to this message.', size=None), + preserve_default=False, + ), + ] -- cgit v1.2.3 From c23d1131fff3ba62431eed0750005b3d5cae9a4c Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sat, 16 Nov 2019 18:43:46 +0100 Subject: Write list test for the offensive message model --- .../apps/api/tests/test_offensive_message.py | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/pydis_site/apps/api/tests/test_offensive_message.py b/pydis_site/apps/api/tests/test_offensive_message.py index a270074b..26729c98 100644 --- a/pydis_site/apps/api/tests/test_offensive_message.py +++ b/pydis_site/apps/api/tests/test_offensive_message.py @@ -69,6 +69,45 @@ class CreationTests(APISubdomainTestCase): }) +class ListTests(APISubdomainTestCase): + @classmethod + def setUpTestData(cls): # noqa + delete_at = datetime.datetime.now() + datetime.timedelta(days=1) + aware_delete_at = delete_at.replace(tzinfo=datetime.timezone.utc) + + cls.messages = [ + { + 'id': 602951077675139072, + 'channel_id': 91284109232308226, + }, + { + 'id': 645298201494159401, + 'channel_id': 592000283102674944 + } + ] + + cls.of1 = OffensiveMessage.objects.create( + **cls.messages[0], + delete_date=aware_delete_at.isoformat() + ) + cls.of2 = OffensiveMessage.objects.create( + **cls.messages[1], + delete_date=aware_delete_at.isoformat() + ) + + # Expected API answer : + cls.messages[0]['delete_date'] = delete_at.isoformat() + 'Z' + cls.messages[1]['delete_date'] = delete_at.isoformat() + 'Z' + + def test_get_data(self): + url = reverse('bot:offensivemessage-list', host='api') + + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + + self.assertEqual(response.json(), self.messages) + + class DeletionTests(APISubdomainTestCase): @classmethod def setUpTestData(cls): # noqa -- cgit v1.2.3 From f55d023edb903ce57fd8b209c76e8f918fc9eb65 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sat, 16 Nov 2019 18:44:55 +0100 Subject: Use direct database test intead of relying on GET --- pydis_site/apps/api/tests/test_offensive_message.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pydis_site/apps/api/tests/test_offensive_message.py b/pydis_site/apps/api/tests/test_offensive_message.py index 26729c98..d5896714 100644 --- a/pydis_site/apps/api/tests/test_offensive_message.py +++ b/pydis_site/apps/api/tests/test_offensive_message.py @@ -127,9 +127,9 @@ class DeletionTests(APISubdomainTestCase): response = self.client.delete(url) self.assertEqual(response.status_code, 204) - url = reverse('bot:offensivemessage-list', host='api') - response = self.client.get(url) - self.assertNotIn(self.valid_offensive_message.id, response.json()) + self.assertFalse( + OffensiveMessage.objects.filter(id=self.valid_offensive_message.id).exists() + ) class NotAllowedMethodsTests(APISubdomainTestCase): -- cgit v1.2.3 From 8e4ed686ebe06e8e15604d204969042efb434b30 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Wed, 20 Nov 2019 18:21:16 +0100 Subject: Test for the attachment image to be in the staff log --- pydis_site/apps/staff/tests/test_logs_view.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pydis_site/apps/staff/tests/test_logs_view.py b/pydis_site/apps/staff/tests/test_logs_view.py index b01e3f3e..1415c558 100644 --- a/pydis_site/apps/staff/tests/test_logs_view.py +++ b/pydis_site/apps/staff/tests/test_logs_view.py @@ -151,6 +151,21 @@ class TestLogsView(TestCase): self.assertInHTML(embed_colour_needle.format(colour=embed_one_colour), html_response) self.assertInHTML(embed_colour_needle.format(colour=embed_two_colour), html_response) + def test_if_both_attachments_are_included_html_response(self): + url = reverse('logs', host="staff", args=(self.deletion_context.id,)) + response = self.client.get(url) + + html_response = response.content.decode() + attachment_needle = 'Attachment' + self.assertInHTML( + attachment_needle.format(url=self.deleted_message_two.attachments[0]), + html_response + ) + self.assertInHTML( + attachment_needle.format(url=self.deleted_message_two.attachments[1]), + html_response + ) + def test_if_html_in_content_is_properly_escaped(self): url = reverse('logs', host="staff", args=(self.deletion_context.id,)) response = self.client.get(url) -- cgit v1.2.3 From f3653925b8ddd4ce5d1c81cd9b1dd94cb0b36b53 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sat, 14 Dec 2019 11:46:37 +0100 Subject: Rename route /bot/offensive-message to /bot/offensive-messages --- pydis_site/apps/api/urls.py | 2 +- pydis_site/apps/api/viewsets/bot/offensive_message.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pydis_site/apps/api/urls.py b/pydis_site/apps/api/urls.py index b1864ba7..4a0281b4 100644 --- a/pydis_site/apps/api/urls.py +++ b/pydis_site/apps/api/urls.py @@ -35,7 +35,7 @@ bot_router.register( NominationViewSet ) bot_router.register( - 'offensive-message', + 'offensive-messages', OffensiveMessageViewSet ) bot_router.register( diff --git a/pydis_site/apps/api/viewsets/bot/offensive_message.py b/pydis_site/apps/api/viewsets/bot/offensive_message.py index f25c14b4..54cb3a38 100644 --- a/pydis_site/apps/api/viewsets/bot/offensive_message.py +++ b/pydis_site/apps/api/viewsets/bot/offensive_message.py @@ -16,7 +16,7 @@ class OffensiveMessageViewSet( View providing CRUD access to offensive messages. ## Routes - ### GET /bot/offensive-message + ### GET /bot/offensive-messages Returns all offensive messages in the database. #### Response format @@ -32,7 +32,7 @@ class OffensiveMessageViewSet( #### Status codes - 200: returned on success - ### POST /bot/offensive-message + ### POST /bot/offensive-messages Create a new offensive message object. #### Request body @@ -46,7 +46,7 @@ class OffensiveMessageViewSet( - 201: returned on success - 400: if the body format is invalid - ### DELETE /bot/offensive-message/ + ### DELETE /bot/offensive-messages/ Delete the offensive message object with the given `id`. #### Status codes -- cgit v1.2.3 From c8207ab9af12e9b068ca3362788c0c164c48e64a Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Tue, 17 Dec 2019 00:05:59 +0100 Subject: Pad the discriminator with zeroes in profile. previously, lemon#0001 would display as just lemon#1. This commit fixes this. All credit goes to @gdude2002 --- pydis_site/utils/account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/utils/account.py b/pydis_site/utils/account.py index e64919de..2d699c88 100644 --- a/pydis_site/utils/account.py +++ b/pydis_site/utils/account.py @@ -73,7 +73,7 @@ class SocialAccountAdapter(DefaultSocialAccountAdapter): """ if social_login.account.provider == "discord": discriminator = social_login.account.extra_data["discriminator"] - data["username"] = f"{data['username']}#{discriminator}" + data["username"] = f"{data['username']}#{discriminator:0>4}" data["name"] = data["username"] return super().populate_user(request, social_login, data) -- cgit v1.2.3 From 3f2adb8ab93bb520d6fb7fb6980585c2fcb41cff Mon Sep 17 00:00:00 2001 From: Jeremiah Boby Date: Mon, 23 Dec 2019 00:39:20 +0000 Subject: Add Code Jam 6 banner to the homepage --- pydis_site/templates/home/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pydis_site/templates/home/index.html b/pydis_site/templates/home/index.html index dfcc6715..3b150767 100644 --- a/pydis_site/templates/home/index.html +++ b/pydis_site/templates/home/index.html @@ -37,11 +37,11 @@

- {# Intro video #} + {# Code Jam banner #}
- + + +
-- cgit v1.2.3 From cc22503ef412c9caa1190c9b5b34a536444ab1bf Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Thu, 26 Dec 2019 21:38:11 +1000 Subject: Use a static discord shield on the readme. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index df0417e4..86509beb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Python Discord: Site -[![Discord](https://img.shields.io/discord/267624335836053506?color=%237289DA&label=Python%20Discord&logo=discord&logoColor=white)](https://discord.gg/2B963hn) +[![Discord](https://img.shields.io/static/v1?label=Python%20Discord&logo=discord&message=%3E30k%20members&color=%237289DA&logoColor=white)](https://discord.gg/2B963hn) [![Build Status](https://dev.azure.com/python-discord/Python%20Discord/_apis/build/status/Site?branchName=master)](https://dev.azure.com/python-discord/Python%20Discord/_build/latest?definitionId=2&branchName=master) [![Tests](https://img.shields.io/azure-devops/tests/python-discord/Python%20Discord/2?compact_message)](https://dev.azure.com/python-discord/Python%20Discord/_apis/build/status/Site?branchName=master) [![Coverage](https://img.shields.io/azure-devops/coverage/python-discord/Python%20Discord/2/master)](https://dev.azure.com/python-discord/Python%20Discord/_apis/build/status/Site?branchName=master) -- cgit v1.2.3 From 643a139bbcee3cc82e33447d809d3008806dd031 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 Jan 2020 11:37:23 +0000 Subject: Bump django from 2.2.6 to 2.2.8 Bumps [django](https://github.com/django/django) from 2.2.6 to 2.2.8. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/2.2.6...2.2.8) Signed-off-by: dependabot[bot] --- Pipfile | 2 +- Pipfile.lock | 178 +++++++++++++++++++++++++++++------------------------------ 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/Pipfile b/Pipfile index cb5776e0..c765d557 100644 --- a/Pipfile +++ b/Pipfile @@ -4,7 +4,7 @@ url = "https://pypi.org/simple" verify_ssl = true [packages] -django = "~=2.2.0" +django = "~=2.2.8" django-crispy-forms = "~=1.7.2" django-environ = "~=0.4.5" django-filter = "~=2.1.0" diff --git a/Pipfile.lock b/Pipfile.lock index 06b49ce7..fea7251c 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "a4bfc709fcdecf5a3bd28326d51625c83a8a7661367cc69dbda20e3a55f1d9d3" + "sha256": "dc3468691aed07cf8a9238256cc1b273669d0331a11e105b2d6adc1e19803020" }, "pipfile-spec": 6, "requires": { @@ -25,10 +25,10 @@ }, "certifi": { "hashes": [ - "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", - "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" ], - "version": "==2019.9.11" + "version": "==2019.11.28" }, "chardet": { "hashes": [ @@ -46,11 +46,11 @@ }, "django": { "hashes": [ - "sha256:4025317ca01f75fc79250ff7262a06d8ba97cd4f82e93394b2a0a6a4a925caeb", - "sha256:a8ca1033acac9f33995eb2209a6bf18a4681c3e5269a878e9a7e0b7384ed1ca3" + "sha256:a4ad4f6f9c6a4b7af7e2deec8d0cbff28501852e5010d6c2dc695d3d1fae7ca0", + "sha256:fa98ec9cc9bf5d72a08ebf3654a9452e761fbb8566e3f80de199cbc15477e891" ], "index": "pypi", - "version": "==2.2.6" + "version": "==2.2.8" }, "django-allauth": { "hashes": [ @@ -121,10 +121,10 @@ }, "django-nyt": { "hashes": [ - "sha256:187f2aae5088c4cf79e7a7caa55c2a9c292722f50cf185c5a738636713ae67ea", - "sha256:5556e2de47a7b710325a33c49314ee3eff7021d638492e957ef2de15c9360143" + "sha256:a696a52a0b729465c062b4808d2ad8c43b439561b2f9654328040c646abb3732", + "sha256:b16bffcfcb468f7b5c70f61de79294a88b7df63859675721d3417507e3440d15" ], - "version": "==1.1.3" + "version": "==1.1.5" }, "django-sekizai": { "hashes": [ @@ -171,24 +171,24 @@ }, "libsass": { "hashes": [ - "sha256:175355d74bd040893d539154016153247ea9775d1655a36441c97a453887a0c0", - "sha256:3113ef32eaf3662c162c250db6883d7a5f177856bfd8bb632a147cb0a95e4fee", - "sha256:312d135e6bd1a137927fed781dab497c05930305265e3d3b1da3b3d916cd97a6", - "sha256:32f8322aad9b6b864b826adb5e193d704d5fb2c816f85a5cc5bf775730e5d024", - "sha256:4252e24c8869d6ce764052f200445331d1881b5c2d283d6131a30d0684b10403", - "sha256:517324814f81cd2642cb1e9fd772e8e50e336c7c8833d50535a731e5b4c84606", - "sha256:607ce32c3b31542e0bf1bc2409627dd7247a3849ba720ec34d23426b96346199", - "sha256:6124594e72ba216b00131795ad5ea5de1e0cf8784e63a01e0c6a4e4c13fc7914", - "sha256:6129063002fc8337b734f5963ac3eb01ead51e9c88c6d27e73ddc9236cb15b2e", - "sha256:6d392ecd6e4de2ccfa3b1953f2da8461a2b7c8c8c17c24e1c335ab3040671c1a", - "sha256:75b38c236be6ca03e3dd3789f3044180fc0836b7c9e4991fcc52a8570f47dc91", - "sha256:9c711d4e4d003fec7f98fe87bb1faf7d88e6d648356413d8b8d9d76bd1844089", - "sha256:b15a0e61bd54764e658bc6931015453fa34d954f87c3b6fd35624e13bcacf69d", - "sha256:bc0c80a4e233b6b791a7f6f99415ab877e8a4d3a45085b68981c97d74dbfc8bf", - "sha256:c22cdc37121b730e5fb87bc8d3eee8c4b1fe219a04d198a535fbd22895c99e27", - "sha256:c5ba74babfb3a6976611312e0026c4668913cdf05e009921e1f54146ccdc02a4" - ], - "version": "==0.19.3" + "sha256:003a65b4facb4c5dbace53fb0f70f61c5aae056a04b4d112a198c3c9674b31f2", + "sha256:0fd8b4337b3b101c6e6afda9112cc0dc4bacb9133b59d75d65968c7317aa3272", + "sha256:338e9ae066bf1fde874e335324d5355c52d2081d978b4f74fc59536564b35b08", + "sha256:4dcfd561fb100250b89496e1362b96f2cc804f689a59731eb0f94f9a9e144f4a", + "sha256:50778d4be269a021ba2bf42b5b8f6ff3704ab96a82175a052680bddf3ba7cc9f", + "sha256:6a51393d75f6e3c812785b0fa0b7d67c54258c28011921f204643b55f7355ec0", + "sha256:74acd9adf506142699dfa292f0e569fdccbd9e7cf619e8226f7117de73566e32", + "sha256:81a013a4c2a614927fd1ef7a386eddabbba695cbb02defe8f31cf495106e974c", + "sha256:845a9573b25c141164972d498855f4ad29367c09e6d76fad12955ad0e1c83013", + "sha256:8b5b6d1a7c4ea1d954e0982b04474cc076286493f6af2d0a13c2e950fbe0be95", + "sha256:9b59afa0d755089c4165516400a39a289b796b5612eeef5736ab7a1ebf96a67c", + "sha256:a7e685466448c9b1bf98243339793978f654a1151eb5c975f09b83c7a226f4c1", + "sha256:c93df526eeef90b1ea4799c1d33b6cd5aea3e9f4633738fb95c1287c13e6b404", + "sha256:e318f06f06847ff49b1f8d086ac9ebce1e63404f7ea329adab92f4f16ba0e00e", + "sha256:fc5f8336750f76f1bfae82f7e9e89ae71438d26fc4597e3ab4c05ca8fcd41d8a", + "sha256:fcb7ab4dc81889e5fc99cafbc2017bc76996f9992fc6b175f7a80edac61d71df" + ], + "version": "==0.19.4" }, "markdown": { "hashes": [ @@ -206,34 +206,30 @@ }, "pillow": { "hashes": [ - "sha256:00fdeb23820f30e43bba78eb9abb00b7a937a655de7760b2e09101d63708b64e", - "sha256:01f948e8220c85eae1aa1a7f8edddcec193918f933fb07aaebe0bfbbcffefbf1", - "sha256:08abf39948d4b5017a137be58f1a52b7101700431f0777bec3d897c3949f74e6", - "sha256:099a61618b145ecb50c6f279666bbc398e189b8bc97544ae32b8fcb49ad6b830", - "sha256:2c1c61546e73de62747e65807d2cc4980c395d4c5600ecb1f47a650c6fa78c79", - "sha256:2ed9c4f694861642401f27dc3cb99772be67cd190e84845c749dae0a06c3bfae", - "sha256:338581b30b908e111be578f0297255f6b57a51358cd16fa0e6f664c9a1f88bff", - "sha256:38c7d48a21cd06fdeee93987147b9b1c55b73b4cfcbf83240568bfbd5adee447", - "sha256:43fd026f613c8e48a25eba1a92f4d2ad7f3903c95d8c33a11611a7717d2ab654", - "sha256:4548236844327a718ce3bb182ab32a16fa2050c61e334e959f554cac052fb0df", - "sha256:5090857876c58885cfa388dc649e5db30aae98a068c26f3fd0ac9d7d9a4d9572", - "sha256:5bbba34f97a26a93f5e8dec469ca4ddd712451418add43da946dbaed7f7a98d2", - "sha256:65a28969a025a0eb4594637b6103201dc4ed2a9508bdab56ac33e43e3081c404", - "sha256:892bb52b70bd5ea9dbbc3ac44f38e84f5a04e9d8b1bff48159d96cb795b81159", - "sha256:8a9becd5cbd5062f973bcd2e7bc79483af310222de112b6541f8af1f93a3cc42", - "sha256:972a7aaeb7c4a2795b52eef52ee991ef040b31009f36deca6207a986607b55f3", - "sha256:97b119c436bfa96a92ac2ca525f7025836d4d4e64b1c9f9eff8dbaf3ff1d86f3", - "sha256:9ba37698e242223f8053cc158f130aee046a96feacbeab65893dbe94f5530118", - "sha256:b1b0e1f626a0f079c0d3696db70132fb1f29aa87c66aecb6501a9b8be64ce9f7", - "sha256:c14c1224fd1a5be2733530d648a316974dbbb3c946913562c6005a76f21ca042", - "sha256:c79a8546c48ae6465189e54e3245a97ddf21161e33ff7eaa42787353417bb2b6", - "sha256:ceb76935ac4ebdf6d7bc845482a4450b284c6ccfb281e34da51d510658ab34d8", - "sha256:e22bffaad04b4d16e1c091baed7f2733fc1ebb91e0c602abf1b6834d17158b1f", - "sha256:ec883b8e44d877bda6f94a36313a1c6063f8b1997aa091628ae2f34c7f97c8d5", - "sha256:f1baa54d50ec031d1a9beb89974108f8f2c0706f49798f4777df879df0e1adb6", - "sha256:f53a5385932cda1e2c862d89460992911a89768c65d176ff8c50cddca4d29bed" - ], - "version": "==6.2.0" + "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be", + "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946", + "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837", + "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f", + "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00", + "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d", + "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533", + "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a", + "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358", + "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda", + "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435", + "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2", + "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313", + "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff", + "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317", + "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2", + "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614", + "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0", + "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386", + "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9", + "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636", + "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865" + ], + "version": "==7.0.0" }, "psycopg2-binary": { "hashes": [ @@ -259,11 +255,13 @@ "sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e", "sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103", "sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6", + "sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1", "sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9", "sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e", "sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f", "sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd", "sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8", + "sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f", "sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4", "sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964", "sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08" @@ -308,6 +306,7 @@ "sha256:861c94442b28cd64af033e88e0f63c66dbd5609f67952dc18694098b47a43f3a", "sha256:957bc6316ffc8463795d56d9953d58e7f32aa5aad1c5ac80bc45c69f3299961e", "sha256:9760c3f56fb5f15852d163429096600906478e9ed2c189a52f2bb21d8a2a986c", + "sha256:9fdfb98a2992de01e8efad2aeed22c825e36db628b144b2d6b93d81fb549f811", "sha256:a4b24703ea818196d0be1dc64b3b57b79c67e8dee0cfa207a4216220912035a7", "sha256:ad7f4968c1ddbf139a306d9b075360d959cc554d994ba5e1f512af9a40e62357", "sha256:b1127d34b90f74faf1707718c57a4193ac028b9f4aec0238638983132297d456", @@ -318,6 +317,7 @@ "sha256:ce777ebdf49ce736fc04abf555b5c41ab3f130127543a689dcf8d4871cd18fe4", "sha256:d8b4bf930b6a19bc9ee982b9163d948c87501ad91b71516924e8ed25fe85d2ee", "sha256:e2a420f2c4d35f3ec0b7e752a80d7bd385e2c5a64f67c05f2d2d74230e3114b6", + "sha256:ef5eb630f541af6b69378d58594be90a0922fa6d6a50a9248c25b9502585f6bf", "sha256:fed899ce96f4f2b4d1b9f338dd145a4040ee1d8a5152213af0dd8d4a4d36e9fe" ], "index": "pypi", @@ -353,17 +353,17 @@ }, "requests-oauthlib": { "hashes": [ - "sha256:bd6533330e8748e94bf0b214775fed487d309b8b8fe823dc45641ebcd9a32f57", - "sha256:d3ed0c8f2e3bbc6b344fa63d6f933745ab394469da38db16bdddb461c7e25140" + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a" ], - "version": "==1.2.0" + "version": "==1.3.0" }, "six": { "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", + "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" ], - "version": "==1.12.0" + "version": "==1.13.0" }, "sorl-thumbnail": { "hashes": [ @@ -381,10 +381,10 @@ }, "urllib3": { "hashes": [ - "sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398", - "sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86" + "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293", + "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745" ], - "version": "==1.25.6" + "version": "==1.25.7" }, "webencodings": { "hashes": [ @@ -569,24 +569,24 @@ }, "gitpython": { "hashes": [ - "sha256:631263cc670aa56ce3d3c414cf0fe2e840f2e913514b138ea28d88a477bbcd21", - "sha256:6e97b9f0954807f30c2dd8e3165731ed6c477a1b365f194b69d81d7940a08332" + "sha256:9c2398ffc3dcb3c40b27324b316f08a4f93ad646d5a6328cafbb871aa79f5e42", + "sha256:c155c6a2653593ccb300462f6ef533583a913e17857cfef8fc617c246b6dc245" ], - "version": "==3.0.3" + "version": "==3.0.5" }, "identify": { "hashes": [ - "sha256:4f1fe9a59df4e80fcb0213086fcf502bc1765a01ea4fe8be48da3b65afd2a017", - "sha256:d8919589bd2a5f99c66302fec0ef9027b12ae150b0b0213999ad3f695fc7296e" + "sha256:6f44e637caa40d1b4cb37f6ed3b262ede74901d28b1cc5b1fc07360871edd65d", + "sha256:72e9c4ed3bc713c7045b762b0d2e2115c572b85abfc1f4604f5a4fd4c6642b71" ], - "version": "==1.4.7" + "version": "==1.4.9" }, "importlib-metadata": { "hashes": [ - "sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26", - "sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af" + "sha256:073a852570f92da5f744a3472af1b61e28e9f78ccf0c9117658dc32b15de7b45", + "sha256:d95141fbfa7ef2ec65cfd945e2af7e5a6ddbd7c8d9a25e66ff3be8e3daf9f60f" ], - "version": "==0.23" + "version": "==1.3.0" }, "mccabe": { "hashes": [ @@ -598,10 +598,10 @@ }, "more-itertools": { "hashes": [ - "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", - "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" + "sha256:b84b238cce0d9adad5ed87e745778d20a3f8487d0f0cb8b8a586816c7496458d", + "sha256:c833ef592a0324bcc6a60e48440da07645063c453880c9477ceb22490aec1564" ], - "version": "==7.2.0" + "version": "==8.0.2" }, "nodeenv": { "hashes": [ @@ -611,10 +611,10 @@ }, "pbr": { "hashes": [ - "sha256:2c8e420cd4ed4cec4e7999ee47409e876af575d4c35a45840d59e8b5f3155ab8", - "sha256:b32c8ccaac7b1a20c0ce00ce317642e6cf231cf038f9875e0280e28af5bf7ac9" + "sha256:139d2625547dbfa5fb0b81daebb39601c478c21956dc57e2e07b74450a8c506b", + "sha256:61aa52a0f18b71c5cc58232d2cf8f8d09cd67fcad60b742a60124cb8d6951488" ], - "version": "==5.4.3" + "version": "==5.4.4" }, "pep8-naming": { "hashes": [ @@ -641,10 +641,10 @@ }, "pydocstyle": { "hashes": [ - "sha256:04c84e034ebb56eb6396c820442b8c4499ac5eb94a3bda88951ac3dc519b6058", - "sha256:66aff87ffe34b1e49bff2dd03a88ce6843be2f3346b0c9814410d34987fbab59" + "sha256:4167fe954b8f27ebbbef2fbcf73c6e8ad1e7bb31488fce44a69fdfc4b0cd0fae", + "sha256:a0de36e549125d0a16a72a8c8c6c9ba267750656e72e466e994c222f1b6e92cb" ], - "version": "==4.0.1" + "version": "==5.0.1" }, "pyflakes": { "hashes": [ @@ -674,10 +674,10 @@ }, "six": { "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", + "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" ], - "version": "==1.12.0" + "version": "==1.13.0" }, "smmap2": { "hashes": [ @@ -742,10 +742,10 @@ }, "virtualenv": { "hashes": [ - "sha256:3e3597e89c73df9313f5566e8fc582bd7037938d15b05329c232ec57a11a7ad5", - "sha256:5d370508bf32e522d79096e8cbea3499d47e624ac7e11e9089f9397a0b3318df" + "sha256:0d62c70883c0342d59c11d0ddac0d954d0431321a41ab20851facf2b222598f3", + "sha256:55059a7a676e4e19498f1aad09b8313a38fcc0cdbe4fdddc0e9b06946d21b4bb" ], - "version": "==16.7.6" + "version": "==16.7.9" }, "zipp": { "hashes": [ -- cgit v1.2.3 From aeece0158dce335ca795c115f9975a5a7ff2163e Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Mon, 6 Jan 2020 13:43:06 +0100 Subject: Adding iframes to HTML whitelist This will allow us to put stuff like YouTube embeds in wiki articles... hopefully. I didn't test it. --- pydis_site/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/settings.py b/pydis_site/settings.py index 66376c4e..e8b71e76 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -376,7 +376,7 @@ WIKI_MARKDOWN_HTML_ATTRIBUTES = { } WIKI_MARKDOWN_HTML_WHITELIST = [ - 'article', 'section', 'button' + 'article', 'section', 'button', 'iframe' ] -- cgit v1.2.3 From 86acb429bafc703684aa0bd47b6495c2044d89dd Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Mon, 6 Jan 2020 14:04:41 +0100 Subject: Adding iframe attributes to attribute whitelist To properly show YouTube-embeds, we need to allow some attributes on `iframe` tags. I've added all attributes that are normal for such an embed, including `width` and `height` (which we may not need if we want to make the frame resize to its parent). --- pydis_site/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pydis_site/settings.py b/pydis_site/settings.py index e8b71e76..72cc0ab9 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -373,6 +373,7 @@ WIKI_MARKDOWN_HTML_ATTRIBUTES = { 'img': ['class', 'id', 'src', 'alt', 'width', 'height'], 'section': ['class', 'id'], 'article': ['class', 'id'], + 'iframe': ['width', 'height', 'src', 'frameborder', 'allow', 'allowfullscreen'], } WIKI_MARKDOWN_HTML_WHITELIST = [ -- cgit v1.2.3 From 8c23efacc061bd0018075aed689d0123fc8d8d84 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 13 Jan 2020 13:08:29 +0100 Subject: Update migration dependency to the latest merged --- pydis_site/apps/api/migrations/0049_deletedmessage_attachments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/apps/api/migrations/0049_deletedmessage_attachments.py b/pydis_site/apps/api/migrations/0049_deletedmessage_attachments.py index 9cbde96d..31ac239a 100644 --- a/pydis_site/apps/api/migrations/0049_deletedmessage_attachments.py +++ b/pydis_site/apps/api/migrations/0049_deletedmessage_attachments.py @@ -7,7 +7,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('api', '0048_add_infractions_unique_constraints_active'), + ('api', '0049_offensivemessage'), ] operations = [ -- cgit v1.2.3 From c4f83481395827d7e6d15ca62e56ae5ea7665aef Mon Sep 17 00:00:00 2001 From: Joseph Date: Sun, 2 Feb 2020 20:08:29 +0000 Subject: Create CODEOWNERS --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..8aa16827 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @core-developers -- cgit v1.2.3 From 824566b157710c0bb64e4bf97124708729d2377a Mon Sep 17 00:00:00 2001 From: Joseph Date: Sun, 2 Feb 2020 22:24:13 +0000 Subject: Update CODEOWNERS --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8aa16827..cf5f1590 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @core-developers +* @python-discord/core-developers -- cgit v1.2.3 From d966231b917357f4e0db901958b30cdd7ef6f4c3 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Mon, 3 Feb 2020 23:44:45 +1000 Subject: Unbleach Wiki Disables the sanitisation of HTML in wiki articles. --- pydis_site/settings.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/pydis_site/settings.py b/pydis_site/settings.py index 72cc0ab9..65ef2463 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -360,25 +360,7 @@ WIKI_MESSAGE_TAG_CSS_CLASS = { messages.WARNING: "is-warning", } -WIKI_MARKDOWN_HTML_STYLES = [ - 'max-width', - 'min-width', - 'margin', - 'padding', - 'width', - 'height', -] - -WIKI_MARKDOWN_HTML_ATTRIBUTES = { - 'img': ['class', 'id', 'src', 'alt', 'width', 'height'], - 'section': ['class', 'id'], - 'article': ['class', 'id'], - 'iframe': ['width', 'height', 'src', 'frameborder', 'allow', 'allowfullscreen'], -} - -WIKI_MARKDOWN_HTML_WHITELIST = [ - 'article', 'section', 'button', 'iframe' -] +WIKI_MARKDOWN_SANITIZE_HTML = False # Wiki permissions -- cgit v1.2.3