From 367c01a7b3cd5cc5ee25644ae92f917ceb00562c Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Fri, 29 Oct 2021 03:19:37 +0400 Subject: Adds Failures Field To Reminders Adds an integer field to reminders, to keep track of how many failed attempts at delivering the reminder were made. Updates documentation and serialization. Signed-off-by: Hassan Abouelela --- .../apps/api/migrations/0074_reminder_failures.py | 18 ++++++++++++++++++ pydis_site/apps/api/models/bot/reminder.py | 4 ++++ pydis_site/apps/api/serializers.py | 10 +++++++++- pydis_site/apps/api/viewsets/bot/reminder.py | 13 ++++++++----- 4 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 pydis_site/apps/api/migrations/0074_reminder_failures.py (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/migrations/0074_reminder_failures.py b/pydis_site/apps/api/migrations/0074_reminder_failures.py new file mode 100644 index 00000000..2860046e --- /dev/null +++ b/pydis_site/apps/api/migrations/0074_reminder_failures.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.14 on 2021-10-27 17:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0073_otn_allow_GT_and_LT'), + ] + + operations = [ + migrations.AddField( + model_name='reminder', + name='failures', + field=models.IntegerField(default=0, help_text='Number of times we attempted to send the reminder and failed.'), + ), + ] diff --git a/pydis_site/apps/api/models/bot/reminder.py b/pydis_site/apps/api/models/bot/reminder.py index 7d968a0e..173900ee 100644 --- a/pydis_site/apps/api/models/bot/reminder.py +++ b/pydis_site/apps/api/models/bot/reminder.py @@ -59,6 +59,10 @@ class Reminder(ModelReprMixin, models.Model): blank=True, help_text="IDs of roles or users to ping with the reminder." ) + failures = models.IntegerField( + default=0, + help_text="Number of times we attempted to send the reminder and failed." + ) def __str__(self): """Returns some info on the current reminder, for display purposes.""" diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index f47bedca..3e213d43 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -231,7 +231,15 @@ class ReminderSerializer(ModelSerializer): model = Reminder fields = ( - 'active', 'author', 'jump_url', 'channel_id', 'content', 'expiration', 'id', 'mentions' + 'active', + 'author', + 'jump_url', + 'channel_id', + 'content', + 'expiration', + 'id', + 'mentions', + 'failures' ) diff --git a/pydis_site/apps/api/viewsets/bot/reminder.py b/pydis_site/apps/api/viewsets/bot/reminder.py index 111660d9..78d7cb3b 100644 --- a/pydis_site/apps/api/viewsets/bot/reminder.py +++ b/pydis_site/apps/api/viewsets/bot/reminder.py @@ -42,7 +42,8 @@ class ReminderViewSet( ... 'expiration': '5018-11-20T15:52:00Z', ... 'id': 11, ... 'channel_id': 634547009956872193, - ... 'jump_url': "https://discord.com/channels///" + ... 'jump_url': "https://discord.com/channels///", + ... 'failures': 3 ... }, ... ... ... ] @@ -67,7 +68,8 @@ class ReminderViewSet( ... 'expiration': '5018-11-20T15:52:00Z', ... 'id': 11, ... 'channel_id': 634547009956872193, - ... 'jump_url': "https://discord.com/channels///" + ... 'jump_url': "https://discord.com/channels///", + ... 'failures': 3 ... } #### Status codes @@ -80,7 +82,7 @@ class ReminderViewSet( #### Request body >>> { ... 'author': int, - ... 'mentions': List[int], + ... 'mentions': list[int], ... 'content': str, ... 'expiration': str, # ISO-formatted datetime ... 'channel_id': int, @@ -98,9 +100,10 @@ class ReminderViewSet( #### Request body >>> { - ... 'mentions': List[int], + ... 'mentions': list[int], ... 'content': str, - ... 'expiration': str # ISO-formatted datetime + ... 'expiration': str, # ISO-formatted datetime + ... 'failures': int ... } #### Status codes -- cgit v1.2.3 From 7353e1ed7003a1198fb00a1e40251b95cf2fdf7e Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Wed, 17 Nov 2021 14:27:45 +0400 Subject: Adds Redirect Filter List Adds a new filter list for URLs which should be treated as redirects and unfurled. Signed-off-by: Hassan Abouelela --- .../apps/api/migrations/0075_add_redirects_filter.py | 18 ++++++++++++++++++ pydis_site/apps/api/models/bot/filter_list.py | 1 + pydis_site/apps/api/viewsets/bot/filter_list.py | 3 ++- 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 pydis_site/apps/api/migrations/0075_add_redirects_filter.py (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/migrations/0075_add_redirects_filter.py b/pydis_site/apps/api/migrations/0075_add_redirects_filter.py new file mode 100644 index 00000000..23dc176f --- /dev/null +++ b/pydis_site/apps/api/migrations/0075_add_redirects_filter.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.14 on 2021-11-17 10:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0074_reminder_failures'), + ] + + operations = [ + migrations.AlterField( + model_name='filterlist', + name='type', + field=models.CharField(choices=[('GUILD_INVITE', 'Guild Invite'), ('FILE_FORMAT', 'File Format'), ('DOMAIN_NAME', 'Domain Name'), ('FILTER_TOKEN', 'Filter Token'), ('REDIRECT', 'Redirect')], help_text='The type of allowlist this is on.', max_length=50), + ), + ] diff --git a/pydis_site/apps/api/models/bot/filter_list.py b/pydis_site/apps/api/models/bot/filter_list.py index d279e137..d30f7213 100644 --- a/pydis_site/apps/api/models/bot/filter_list.py +++ b/pydis_site/apps/api/models/bot/filter_list.py @@ -12,6 +12,7 @@ class FilterList(ModelTimestampMixin, ModelReprMixin, models.Model): 'FILE_FORMAT ' 'DOMAIN_NAME ' 'FILTER_TOKEN ' + 'REDIRECT ' ) type = models.CharField( max_length=50, diff --git a/pydis_site/apps/api/viewsets/bot/filter_list.py b/pydis_site/apps/api/viewsets/bot/filter_list.py index 2cb21ab9..4b05acee 100644 --- a/pydis_site/apps/api/viewsets/bot/filter_list.py +++ b/pydis_site/apps/api/viewsets/bot/filter_list.py @@ -59,7 +59,8 @@ class FilterListViewSet(ModelViewSet): ... ["GUILD_INVITE","Guild Invite"], ... ["FILE_FORMAT","File Format"], ... ["DOMAIN_NAME","Domain Name"], - ... ["FILTER_TOKEN","Filter Token"] + ... ["FILTER_TOKEN","Filter Token"], + ... ["REDIRECT", "Redirect"] ... ] #### Status codes -- cgit v1.2.3 From 855bf5e7c7e54e9f8e4544545026c47092b52a11 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Mon, 22 Nov 2021 20:36:21 +0000 Subject: Only calc activity blocks when <1k messages We only truly care about how many activity blocks a user has when they have a small number of messages, as we only use this for the voice gate. If a user has more than say 1k messages, then we really don't need to calculate their activity blocks, as it's quite an expensive query with many messages. --- pydis_site/apps/api/viewsets/bot/user.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/viewsets/bot/user.py b/pydis_site/apps/api/viewsets/bot/user.py index 22d13dc4..ed661323 100644 --- a/pydis_site/apps/api/viewsets/bot/user.py +++ b/pydis_site/apps/api/viewsets/bot/user.py @@ -271,9 +271,15 @@ class UserViewSet(ModelViewSet): with Metricity() as metricity: try: data = metricity.user(user.id) + data["total_messages"] = metricity.total_messages(user.id) + if data["total_messages"] < 1000: + # Only calculate and return activity_blocks if the user has a small amount + # of messages, as calculating activity_blocks is expensive. + # 1000 message chosen as an arbitrarily large number. + data["activity_blocks"] = metricity.total_message_blocks(user.id) + data["voice_banned"] = voice_banned - data["activity_blocks"] = metricity.total_message_blocks(user.id) return Response(data, status=status.HTTP_200_OK) except NotFoundError: return Response(dict(detail="User not found in metricity"), -- cgit v1.2.3 From c8d1513b8f8cb21482180ce19d69a107adefe4e2 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Mon, 22 Nov 2021 20:38:41 +0000 Subject: Make metricity test order insensitive We only actually care that thee key:value pairs are equal, the order of them isn't actually important. The naming of `assertCountEqual` is a little misleading, since it actually tests that the first sequence contains the same elements as second, regardless of their order. See https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertCountEqual --- pydis_site/apps/api/tests/test_users.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/tests/test_users.py b/pydis_site/apps/api/tests/test_users.py index 295bcf64..550c7240 100644 --- a/pydis_site/apps/api/tests/test_users.py +++ b/pydis_site/apps/api/tests/test_users.py @@ -408,7 +408,7 @@ class UserMetricityTests(AuthenticatedAPITestCase): in_guild=True, ) - def test_get_metricity_data(self): + def test_get_metricity_data_under_1k(self): # Given joined_at = "foo" total_messages = 1 @@ -421,7 +421,7 @@ class UserMetricityTests(AuthenticatedAPITestCase): # Then self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), { + self.assertCountEqual(response.json(), { "joined_at": joined_at, "total_messages": total_messages, "voice_banned": False, -- cgit v1.2.3 From 78b2f3b8ed46d23015ab2f765504572f672f4567 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Mon, 22 Nov 2021 20:38:58 +0000 Subject: Add metricity test for users >1k messages --- pydis_site/apps/api/tests/test_users.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/tests/test_users.py b/pydis_site/apps/api/tests/test_users.py index 550c7240..81bfd43b 100644 --- a/pydis_site/apps/api/tests/test_users.py +++ b/pydis_site/apps/api/tests/test_users.py @@ -428,6 +428,25 @@ class UserMetricityTests(AuthenticatedAPITestCase): "activity_blocks": total_blocks }) + def test_get_metricity_data_over_1k(self): + # Given + joined_at = "foo" + total_messages = 1001 + total_blocks = 1001 + self.mock_metricity_user(joined_at, total_messages, total_blocks, []) + + # When + url = reverse('api:bot:user-metricity-data', args=[0]) + response = self.client.get(url) + + # Then + self.assertEqual(response.status_code, 200) + self.assertCountEqual(response.json(), { + "joined_at": joined_at, + "total_messages": total_messages, + "voice_banned": False, + }) + def test_no_metricity_user(self): # Given self.mock_no_metricity_user() -- cgit v1.2.3 From 5b1bb82165d188a571c8999f17ef52f3856c9518 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 23 Nov 2021 16:29:06 +0000 Subject: Alter message query to leverage index Previously this query would convert each row to an array just to check if it matched or not. By changing EXCLUDE_CHANNELS to a tuple instead of a list, it doesn't get passed as an array, so we can do a simple NOT IN check. This will also allow us to add an index with this condition to speed it up further. --- pydis_site/apps/api/models/bot/metricity.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/models/bot/metricity.py b/pydis_site/apps/api/models/bot/metricity.py index 33fb7ad7..901f191a 100644 --- a/pydis_site/apps/api/models/bot/metricity.py +++ b/pydis_site/apps/api/models/bot/metricity.py @@ -4,10 +4,10 @@ from django.db import connections BLOCK_INTERVAL = 10 * 60 # 10 minute blocks -EXCLUDE_CHANNELS = [ +EXCLUDE_CHANNELS = ( "267659945086812160", # Bot commands "607247579608121354" # SeasonalBot commands -] +) class NotFoundError(Exception): @@ -46,12 +46,12 @@ class Metricity: self.cursor.execute( """ SELECT - COUNT(*) + COUNT(*) FROM messages WHERE - author_id = '%s' - AND NOT is_deleted - AND NOT %s::varchar[] @> ARRAY[channel_id] + author_id = '%s' + AND NOT is_deleted + AND channel_id NOT IN %s """, [user_id, EXCLUDE_CHANNELS] ) @@ -79,7 +79,7 @@ class Metricity: WHERE author_id='%s' AND NOT is_deleted - AND NOT %s::varchar[] @> ARRAY[channel_id] + AND channel_id NOT IN %s GROUP BY interval ) block_query; """, -- cgit v1.2.3 From 61f9daed8d71046351e60c57ccdbf34443085561 Mon Sep 17 00:00:00 2001 From: Izan Date: Wed, 10 Nov 2021 22:44:20 +0000 Subject: Add `dm_sent` field to infractions model & serializer --- .../apps/api/migrations/0075_infraction_dm_sent.py | 18 ++++++++++++++++++ pydis_site/apps/api/models/bot/infraction.py | 4 ++++ pydis_site/apps/api/serializers.py | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 pydis_site/apps/api/migrations/0075_infraction_dm_sent.py (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/migrations/0075_infraction_dm_sent.py b/pydis_site/apps/api/migrations/0075_infraction_dm_sent.py new file mode 100644 index 00000000..c0ac709d --- /dev/null +++ b/pydis_site/apps/api/migrations/0075_infraction_dm_sent.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.14 on 2021-11-10 22:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0074_reminder_failures'), + ] + + operations = [ + migrations.AddField( + model_name='infraction', + name='dm_sent', + field=models.BooleanField(help_text='Whether a DM was sent to the user when infraction was applied.', null=True), + ), + ] diff --git a/pydis_site/apps/api/models/bot/infraction.py b/pydis_site/apps/api/models/bot/infraction.py index 60c1e8dd..913631d4 100644 --- a/pydis_site/apps/api/models/bot/infraction.py +++ b/pydis_site/apps/api/models/bot/infraction.py @@ -57,6 +57,10 @@ class Infraction(ModelReprMixin, models.Model): default=False, help_text="Whether the infraction is a shadow infraction." ) + dm_sent = models.BooleanField( + null=True, + help_text="Whether a DM was sent to the user when infraction was applied." + ) def __str__(self): """Returns some info on the current infraction, for display purposes.""" diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index 3e213d43..f6801597 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -145,7 +145,7 @@ class InfractionSerializer(ModelSerializer): model = Infraction fields = ( - 'id', 'inserted_at', 'expires_at', 'active', 'user', 'actor', 'type', 'reason', 'hidden' + 'id', 'inserted_at', 'expires_at', 'active', 'user', 'actor', 'type', 'reason', 'hidden', 'dm_sent' ) validators = [ UniqueTogetherValidator( -- cgit v1.2.3 From 1e3725d8f6ef1a601c12054db3d913e447b51866 Mon Sep 17 00:00:00 2001 From: Izan Date: Fri, 12 Nov 2021 14:31:52 +0000 Subject: Update documentation to include `dm_sent` field --- pydis_site/apps/api/viewsets/bot/infraction.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/viewsets/bot/infraction.py b/pydis_site/apps/api/viewsets/bot/infraction.py index f8b0cb9d..8a48ed1f 100644 --- a/pydis_site/apps/api/viewsets/bot/infraction.py +++ b/pydis_site/apps/api/viewsets/bot/infraction.py @@ -70,7 +70,8 @@ class InfractionViewSet( ... 'actor': 125435062127820800, ... 'type': 'ban', ... 'reason': 'He terk my jerb!', - ... 'hidden': True + ... 'hidden': True, + ... 'dm_sent': True ... } ... ] @@ -100,7 +101,8 @@ class InfractionViewSet( ... 'hidden': True, ... 'type': 'ban', ... 'reason': 'He terk my jerb!', - ... 'user': 172395097705414656 + ... 'user': 172395097705414656, + ... 'dm_sent': False ... } #### Response format @@ -118,7 +120,8 @@ class InfractionViewSet( >>> { ... 'active': True, ... 'expires_at': '4143-02-15T21:04:31+00:00', - ... 'reason': 'durka derr' + ... 'reason': 'durka derr', + ... 'dm_sent': True ... } #### Response format -- cgit v1.2.3 From 546a2d18bb52a0b4f1fc31de765119623a97f7fa Mon Sep 17 00:00:00 2001 From: Izan Date: Thu, 25 Nov 2021 10:44:06 +0000 Subject: Fix linting --- pydis_site/apps/api/serializers.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index f6801597..de2fccff 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -145,7 +145,16 @@ class InfractionSerializer(ModelSerializer): model = Infraction fields = ( - 'id', 'inserted_at', 'expires_at', 'active', 'user', 'actor', 'type', 'reason', 'hidden', 'dm_sent' + 'id', + 'inserted_at', + 'expires_at', + 'active', + 'user', + 'actor', + 'type', + 'reason', + 'hidden', + 'dm_sent' ) validators = [ UniqueTogetherValidator( -- cgit v1.2.3 From 454ad492229253ae675f4ba956c74edf32f41c2a Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Thu, 25 Nov 2021 20:41:16 +0100 Subject: Merge migrations with upstream --- pydis_site/apps/api/migrations/0076_merge_20211125_1941.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 pydis_site/apps/api/migrations/0076_merge_20211125_1941.py (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/migrations/0076_merge_20211125_1941.py b/pydis_site/apps/api/migrations/0076_merge_20211125_1941.py new file mode 100644 index 00000000..097d0a0c --- /dev/null +++ b/pydis_site/apps/api/migrations/0076_merge_20211125_1941.py @@ -0,0 +1,14 @@ +# Generated by Django 3.0.14 on 2021-11-25 19:41 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0075_infraction_dm_sent'), + ('api', '0075_add_redirects_filter'), + ] + + operations = [ + ] -- cgit v1.2.3 From f093907393b4f479f62409286831b938ba65c558 Mon Sep 17 00:00:00 2001 From: D0rs4n <41237606+D0rs4n@users.noreply.github.com> Date: Tue, 31 Aug 2021 16:27:18 +0200 Subject: Create a signal to unassign roles from user when deleted Add a signal to the api app that automatically unassigns deleted roles from users that have them --- pydis_site/apps/api/__init__.py | 1 + pydis_site/apps/api/apps.py | 10 +++++++++- pydis_site/apps/api/signals.py | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 pydis_site/apps/api/signals.py (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/__init__.py b/pydis_site/apps/api/__init__.py index e69de29b..afa5b4d5 100644 --- a/pydis_site/apps/api/__init__.py +++ b/pydis_site/apps/api/__init__.py @@ -0,0 +1 @@ +default_app_config = 'pydis_site.apps.api.apps.ApiConfig' diff --git a/pydis_site/apps/api/apps.py b/pydis_site/apps/api/apps.py index 76810b2e..18eda9e3 100644 --- a/pydis_site/apps/api/apps.py +++ b/pydis_site/apps/api/apps.py @@ -4,4 +4,12 @@ from django.apps import AppConfig class ApiConfig(AppConfig): """Django AppConfig for the API app.""" - name = 'api' + name = 'pydis_site.apps.api' + + def ready(self) -> None: + """ + Gets called as soon as the registry is fully populated. + + https://docs.djangoproject.com/en/3.2/ref/applications/#django.apps.AppConfig.ready + """ + import pydis_site.apps.api.signals # noqa: F401 diff --git a/pydis_site/apps/api/signals.py b/pydis_site/apps/api/signals.py new file mode 100644 index 00000000..c69704b1 --- /dev/null +++ b/pydis_site/apps/api/signals.py @@ -0,0 +1,12 @@ +from django.db.models.signals import pre_delete +from django.dispatch import receiver + +from pydis_site.apps.api.models.bot import Role, User + + +@receiver(signal=pre_delete, sender=Role) +def delete_role_from_user(sender: Role, instance: Role, **kwargs) -> None: + """Unassigns the Role (instance) that is being deleted from every user that has it.""" + for user in User.objects.filter(roles__contains=[instance.id]): + del user.roles[user.roles.index(instance.id)] + user.save() -- cgit v1.2.3 From 0f24bdcd0ba261da045ac73e8567239eb63c6fc6 Mon Sep 17 00:00:00 2001 From: D0rs4n <41237606+D0rs4n@users.noreply.github.com> Date: Tue, 31 Aug 2021 17:54:39 +0200 Subject: Add test to check role unassignment Create a test that checks if a role gets deleted it will also get unassigned from the user --- pydis_site/apps/api/tests/test_roles.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/tests/test_roles.py b/pydis_site/apps/api/tests/test_roles.py index d39cea4d..7c968852 100644 --- a/pydis_site/apps/api/tests/test_roles.py +++ b/pydis_site/apps/api/tests/test_roles.py @@ -1,7 +1,8 @@ from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import Role +from ..models import Role, User + class CreationTests(AuthenticatedAPITestCase): @@ -35,6 +36,20 @@ class CreationTests(AuthenticatedAPITestCase): permissions=6, position=0, ) + cls.role_to_delete = Role.objects.create( + id=7, + name="role to delete", + colour=7, + permissions=7, + position=0, + ) + cls.role_unassigned_test_user = User.objects.create( + id=8, + name="role_unassigned_test_user", + discriminator="0000", + roles=[cls.role_to_delete.id], + in_guild=True + ) def _validate_roledict(self, role_dict: dict) -> None: """Helper method to validate a dict representing a role.""" @@ -181,6 +196,11 @@ class CreationTests(AuthenticatedAPITestCase): response = self.client.delete(url) self.assertEqual(response.status_code, 204) + def test_role_delete_unassigned(self): + """Tests if the deleted Role gets unassigned from the user.""" + self.role_to_delete.delete() + self.assertEqual(self.role_unassigned_test_user.roles, []) + def test_role_detail_404_all_methods(self): """Tests detail view with non-existing ID.""" url = reverse('api:bot:role-detail', args=(20190815,)) -- cgit v1.2.3 From 9d255dcf3daafde71071ad75b000077a861da659 Mon Sep 17 00:00:00 2001 From: D0rs4n <41237606+D0rs4n@users.noreply.github.com> Date: Tue, 31 Aug 2021 18:49:21 +0200 Subject: Patch roles test to use fresh instance from the DB --- pydis_site/apps/api/tests/test_roles.py | 1 + 1 file changed, 1 insertion(+) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/tests/test_roles.py b/pydis_site/apps/api/tests/test_roles.py index 7c968852..88c0256b 100644 --- a/pydis_site/apps/api/tests/test_roles.py +++ b/pydis_site/apps/api/tests/test_roles.py @@ -199,6 +199,7 @@ class CreationTests(AuthenticatedAPITestCase): def test_role_delete_unassigned(self): """Tests if the deleted Role gets unassigned from the user.""" self.role_to_delete.delete() + self.role_unassigned_test_user.refresh_from_db() self.assertEqual(self.role_unassigned_test_user.roles, []) def test_role_detail_404_all_methods(self): -- cgit v1.2.3 From f34a52016bd5a7d50c1146d6fbd213ce889f58c7 Mon Sep 17 00:00:00 2001 From: D0rs4n <41237606+D0rs4n@users.noreply.github.com> Date: Tue, 31 Aug 2021 19:21:36 +0200 Subject: Patch signals to use post_delete, instead of pre_delete From now on the signal will only get executed after the Role has been deleted The commit also introduces minor changes in the tests of roles --- pydis_site/apps/api/signals.py | 4 ++-- pydis_site/apps/api/tests/test_roles.py | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/signals.py b/pydis_site/apps/api/signals.py index c69704b1..5c26bfb6 100644 --- a/pydis_site/apps/api/signals.py +++ b/pydis_site/apps/api/signals.py @@ -1,10 +1,10 @@ -from django.db.models.signals import pre_delete +from django.db.models.signals import post_delete from django.dispatch import receiver from pydis_site.apps.api.models.bot import Role, User -@receiver(signal=pre_delete, sender=Role) +@receiver(signal=post_delete, sender=Role) def delete_role_from_user(sender: Role, instance: Role, **kwargs) -> None: """Unassigns the Role (instance) that is being deleted from every user that has it.""" for user in User.objects.filter(roles__contains=[instance.id]): diff --git a/pydis_site/apps/api/tests/test_roles.py b/pydis_site/apps/api/tests/test_roles.py index 88c0256b..73c80c77 100644 --- a/pydis_site/apps/api/tests/test_roles.py +++ b/pydis_site/apps/api/tests/test_roles.py @@ -4,7 +4,6 @@ from .base import AuthenticatedAPITestCase from ..models import Role, User - class CreationTests(AuthenticatedAPITestCase): @classmethod def setUpTestData(cls): @@ -96,11 +95,11 @@ class CreationTests(AuthenticatedAPITestCase): url = reverse('api:bot:role-list') response = self.client.get(url) - self.assertContains(response, text="id", count=4, status_code=200) + self.assertContains(response, text="id", count=5, status_code=200) roles = response.json() self.assertIsInstance(roles, list) - self.assertEqual(len(roles), 4) + self.assertEqual(len(roles), 5) for role in roles: self._validate_roledict(role) -- cgit v1.2.3 From 3f4adf3768123c870f9da38a23b189862a7b9502 Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Sat, 27 Nov 2021 13:28:23 +0100 Subject: Migrate to generic `JSONField` --- .../api/migrations/0077_use_generic_jsonfield.py | 25 ++++++++++++++++++++++ pydis_site/apps/api/models/bot/bot_setting.py | 3 +-- pydis_site/apps/api/models/bot/message.py | 2 +- pydis_site/apps/api/models/utils.py | 3 +-- 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 pydis_site/apps/api/migrations/0077_use_generic_jsonfield.py (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/migrations/0077_use_generic_jsonfield.py b/pydis_site/apps/api/migrations/0077_use_generic_jsonfield.py new file mode 100644 index 00000000..9e8f2fb9 --- /dev/null +++ b/pydis_site/apps/api/migrations/0077_use_generic_jsonfield.py @@ -0,0 +1,25 @@ +# Generated by Django 3.1.13 on 2021-11-27 12:27 + +import django.contrib.postgres.fields +from django.db import migrations, models +import pydis_site.apps.api.models.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0076_merge_20211125_1941'), + ] + + operations = [ + migrations.AlterField( + model_name='botsetting', + name='data', + field=models.JSONField(help_text='The actual settings of this setting.'), + ), + migrations.AlterField( + model_name='deletedmessage', + name='embeds', + field=django.contrib.postgres.fields.ArrayField(base_field=models.JSONField(validators=[pydis_site.apps.api.models.utils.validate_embed]), blank=True, help_text='Embeds attached to this message.', size=None), + ), + ] diff --git a/pydis_site/apps/api/models/bot/bot_setting.py b/pydis_site/apps/api/models/bot/bot_setting.py index 2a3944f8..1bcb1ae6 100644 --- a/pydis_site/apps/api/models/bot/bot_setting.py +++ b/pydis_site/apps/api/models/bot/bot_setting.py @@ -1,4 +1,3 @@ -from django.contrib.postgres import fields as pgfields from django.core.exceptions import ValidationError from django.db import models @@ -24,6 +23,6 @@ class BotSetting(ModelReprMixin, models.Model): max_length=50, validators=(validate_bot_setting_name,) ) - data = pgfields.JSONField( + data = models.JSONField( help_text="The actual settings of this setting." ) diff --git a/pydis_site/apps/api/models/bot/message.py b/pydis_site/apps/api/models/bot/message.py index 60e2a553..bab3368d 100644 --- a/pydis_site/apps/api/models/bot/message.py +++ b/pydis_site/apps/api/models/bot/message.py @@ -48,7 +48,7 @@ class Message(ModelReprMixin, models.Model): blank=True ) embeds = pgfields.ArrayField( - pgfields.JSONField( + models.JSONField( validators=(validate_embed,) ), blank=True, diff --git a/pydis_site/apps/api/models/utils.py b/pydis_site/apps/api/models/utils.py index 0e220a1d..859394d2 100644 --- a/pydis_site/apps/api/models/utils.py +++ b/pydis_site/apps/api/models/utils.py @@ -103,11 +103,10 @@ def validate_embed(embed: Any) -> None: Example: - >>> from django.contrib.postgres import fields as pgfields >>> from django.db import models >>> from pydis_site.apps.api.models.utils import validate_embed >>> class MyMessage(models.Model): - ... embed = pgfields.JSONField( + ... embed = models.JSONField( ... validators=( ... validate_embed, ... ) -- cgit v1.2.3 From 953f232d47ff4e07baeaffa8add7912ff05d6457 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Sat, 11 Dec 2021 13:59:40 +0000 Subject: Use new approx message count view We have added a new view to metricity that will keep track of an approximate message count, updating every 10 seconds. By doing this, we avoid running a query against the whole message table every time we want to get a user's messages. --- pydis_site/apps/api/models/bot/metricity.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/models/bot/metricity.py b/pydis_site/apps/api/models/bot/metricity.py index 901f191a..52e946ac 100644 --- a/pydis_site/apps/api/models/bot/metricity.py +++ b/pydis_site/apps/api/models/bot/metricity.py @@ -46,14 +46,12 @@ class Metricity: self.cursor.execute( """ SELECT - COUNT(*) - FROM messages + message_count + FROM user_has_approx_message_count WHERE author_id = '%s' - AND NOT is_deleted - AND channel_id NOT IN %s """, - [user_id, EXCLUDE_CHANNELS] + [user_id] ) values = self.cursor.fetchone() -- cgit v1.2.3