diff options
| author | 2019-09-06 09:32:30 +0200 | |
|---|---|---|
| committer | 2019-09-06 09:32:30 +0200 | |
| commit | ae6538a46a74cf8d7bb2ef796a5a82f7623c4e24 (patch) | |
| tree | 970c8384bf6a635fbc10624a027d123870c38871 /pydis_site/apps/api | |
| parent | Merge pull request #240 from python-discord/update-contrib (diff) | |
| parent | Applying PR Feedback: Colour constants for readability & absolute import (diff) | |
Merge pull request #238 from python-discord/django-deleted-messages-frontend
Deleted Messages Front-End
Diffstat (limited to 'pydis_site/apps/api')
| -rw-r--r-- | pydis_site/apps/api/models/bot/deleted_message.py | 5 | ||||
| -rw-r--r-- | pydis_site/apps/api/models/bot/message.py | 10 | ||||
| -rw-r--r-- | pydis_site/apps/api/models/bot/tag.py | 17 | ||||
| -rw-r--r-- | pydis_site/apps/api/tests/test_validators.py | 39 | 
4 files changed, 68 insertions, 3 deletions
| diff --git a/pydis_site/apps/api/models/bot/deleted_message.py b/pydis_site/apps/api/models/bot/deleted_message.py index eb7f4c89..1eb4516e 100644 --- a/pydis_site/apps/api/models/bot/deleted_message.py +++ b/pydis_site/apps/api/models/bot/deleted_message.py @@ -12,3 +12,8 @@ class DeletedMessage(Message):          help_text="The deletion context this message is part of.",          on_delete=models.CASCADE      ) + +    class Meta: +        """Sets the default ordering for list views to oldest first.""" + +        ordering = ["id"] diff --git a/pydis_site/apps/api/models/bot/message.py b/pydis_site/apps/api/models/bot/message.py index 6b566620..31316a01 100644 --- a/pydis_site/apps/api/models/bot/message.py +++ b/pydis_site/apps/api/models/bot/message.py @@ -1,6 +1,9 @@ +from datetime import datetime +  from django.contrib.postgres import fields as pgfields  from django.core.validators import MinValueValidator  from django.db import models +from django.utils import timezone  from pydis_site.apps.api.models.bot.tag import validate_tag_embed  from pydis_site.apps.api.models.bot.user import User @@ -49,6 +52,13 @@ class Message(ModelReprMixin, models.Model):          help_text="Embeds attached to this message."      ) +    @property +    def timestamp(self) -> datetime: +        """Attribute that represents the message timestamp as derived from the snowflake id.""" +        tz_naive_datetime = datetime.utcfromtimestamp(((self.id >> 22) + 1420070400000) / 1000) +        tz_aware_datetime = timezone.make_aware(tz_naive_datetime, timezone=timezone.utc) +        return tz_aware_datetime +      class Meta:          """Metadata provided for Django's ORM.""" diff --git a/pydis_site/apps/api/models/bot/tag.py b/pydis_site/apps/api/models/bot/tag.py index 01b49525..de4eab30 100644 --- a/pydis_site/apps/api/models/bot/tag.py +++ b/pydis_site/apps/api/models/bot/tag.py @@ -1,4 +1,5 @@  from collections.abc import Mapping +from typing import Any  from django.contrib.postgres import fields as pgfields  from django.core.exceptions import ValidationError @@ -8,17 +9,31 @@ from django.db import models  from pydis_site.apps.api.models.utils import ModelReprMixin +def is_bool_validator(value: Any) -> None: +    """Validates if a given value is of type bool.""" +    if not isinstance(value, bool): +        raise ValidationError(f"This field must be of type bool, not {type(value)}.") + +  def validate_tag_embed_fields(fields):      """Raises a ValidationError if any of the given embed fields is invalid."""      field_validators = {          'name': (MaxLengthValidator(limit_value=256),), -        'value': (MaxLengthValidator(limit_value=1024),) +        'value': (MaxLengthValidator(limit_value=1024),), +        'inline': (is_bool_validator,),      } +    required_fields = ('name', 'value') +      for field in fields:          if not isinstance(field, Mapping):              raise ValidationError("Embed fields must be a mapping.") +        if not all(required_field in field for required_field in required_fields): +            raise ValidationError( +                f"Embed fields must contain the following fields: {', '.join(required_fields)}." +            ) +          for field_name, value in field.items():              if field_name not in field_validators:                  raise ValidationError(f"Unknown embed field field: {field_name!r}.") diff --git a/pydis_site/apps/api/tests/test_validators.py b/pydis_site/apps/api/tests/test_validators.py index ffa2f61e..4222f0c0 100644 --- a/pydis_site/apps/api/tests/test_validators.py +++ b/pydis_site/apps/api/tests/test_validators.py @@ -119,18 +119,53 @@ class TagEmbedValidatorTests(TestCase):                          'value': "LOOK AT ME"                      },                      { +                        'name': "Totally valid", +                        'value': "LOOK AT ME",                          'oh': "what is this key?"                      }                  ]              }) +    def test_rejects_missing_required_field_field(self): +        with self.assertRaises(ValidationError): +            validate_tag_embed({ +                'fields': [ +                    { +                        'name': "Totally valid", +                        'inline': True, +                    } +                ] +            }) + +    def test_rejects_invalid_inline_field_field(self): +        with self.assertRaises(ValidationError): +            validate_tag_embed({ +                'fields': [ +                    { +                        'name': "Totally valid", +                        'value': "LOOK AT ME", +                        'inline': "Totally not a boolean", +                    } +                ] +            }) +      def test_allows_valid_fields(self):          validate_tag_embed({              'fields': [                  {                      'name': "valid", -                    'value': "field" -                } +                    'value': "field", +                }, +                { +                    'name': "valid", +                    'value': "field", +                    'inline': False, +                }, +                { +                    'name': "valid", +                    'value': "field", +                    'inline': True, +                },              ]          }) | 
