diff options
| author | 2021-12-22 18:18:22 +0100 | |
|---|---|---|
| committer | 2021-12-22 18:18:22 +0100 | |
| commit | af3980fe65b997287ceaf68e53ce3ab7bf4607e5 (patch) | |
| tree | be002681c60744de18cb4b453fa5f86d9016537b /pydis_site | |
| parent | Prepare FilterList and Filter models, serializers for the new filter schema (diff) | |
Patch Filter/FilterList's default values and add new fields
- Patch default values, so that further implementations can be performed on the bot side
- Add three new fields: "send_alert", and in settings under the "server_message" field: "send_message_text", and "server_message_embed" fields.
- Patch documentation, and validators accordingly.
- Perform further patches, and minor corrections.
Diffstat (limited to 'pydis_site')
7 files changed, 234 insertions, 61 deletions
diff --git a/pydis_site/apps/api/migrations/0070_new_filter_schema.py b/pydis_site/apps/api/migrations/0070_new_filter_schema.py index 8716cbad..f56c29f8 100644 --- a/pydis_site/apps/api/migrations/0070_new_filter_schema.py +++ b/pydis_site/apps/api/migrations/0070_new_filter_schema.py @@ -1,4 +1,5 @@  # Modified migration file to migrate existing filters to the new one +from datetime import timedelta  import django.contrib.postgres.fields  from django.apps.registry import Apps @@ -18,20 +19,27 @@ def forward(apps: Apps, schema_editor: BaseDatabaseSchemaEditor) -> None:      for name, type_ in OLD_LIST_NAMES:          objects = filter_list_old.objects.filter(type=name) +        if name == "DOMAIN_NAME": +            dm_content = "Your URL has been removed because it matched a blacklisted domain: {match}" +        elif name == "GUILD_INVITE": +            dm_content = "Per Rule 6, your invite link has been removed. " \ +                         "Our server rules can be found here: https://pythondiscord.com/pages/rules" +        else: +            dm_content = ""          list_ = filter_list.objects.create(              name=name.lower(),              list_type=1 if type_ == "ALLOW" else 0, -            ping_type=["onduty"], +            ping_type=(["onduty"] if name != "FILE_FORMAT" else []),              filter_dm=True, -            dm_ping_type=["onduty"], -            delete_messages=True, -            bypass_roles=[267630620367257601], -            enabled=False, -            dm_content=None, -            infraction_type=None, +            dm_ping_type=[], +            delete_messages=(True if name != "FILTER_TOKEN" else False), +            bypass_roles=["staff"], +            enabled=True, +            dm_content=dm_content, +            infraction_type="",              infraction_reason="", -            infraction_duration=None, +            infraction_duration=timedelta(seconds=0),              disallowed_channels=[],              disallowed_categories=[],              allowed_channels=[], @@ -84,7 +92,7 @@ class Migration(migrations.Migration):                  ('filter_dm', models.BooleanField(help_text='Whether DMs should be filtered.', null=True)),                  ('dm_ping_type', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=20), help_text='Who to ping when this filter triggers on a DM.', size=None, validators=[pydis_site.apps.api.models.bot.filters.validate_ping_field], null=True)),                  ('delete_messages', models.BooleanField(help_text='Whether this filter should delete messages triggering it.', null=True)), -                ('bypass_roles', django.contrib.postgres.fields.ArrayField(base_field=models.BigIntegerField(), help_text='Roles and users who can bypass this filter.', size=None, null=True)), +                ('bypass_roles', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=100), help_text='Roles and users who can bypass this filter.', size=None, validators=[pydis_site.apps.api.models.bot.filters.validate_bypass_roles_field], null=True)),                  ('enabled', models.BooleanField(help_text='Whether this filter is currently enabled.', null=True)),                  ('dm_content', models.CharField(help_text='The DM to send to a user triggering this filter.', max_length=1000, null=True)),                  ('infraction_type', models.CharField(choices=[('note', 'Note'), ('warning', 'Warning'), ('watch', 'Watch'), ('mute', 'Mute'), ('kick', 'Kick'), ('ban', 'Ban'), ('superstar', 'Superstar'), ('voice_ban', 'Voice Ban')], help_text='The infraction to apply to this user.', max_length=9, null=True)), @@ -106,7 +114,7 @@ class Migration(migrations.Migration):                  ('filter_dm', models.BooleanField(help_text='Whether DMs should be filtered.')),                  ('dm_ping_type', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=20), help_text='Who to ping when this filter triggers on a DM.', size=None, validators=[pydis_site.apps.api.models.bot.filters.validate_ping_field])),                  ('delete_messages', models.BooleanField(help_text='Whether this filter should delete messages triggering it.')), -                ('bypass_roles', django.contrib.postgres.fields.ArrayField(base_field=models.BigIntegerField(), help_text='Roles and users who can bypass this filter.', size=None)), +                ('bypass_roles', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=100), help_text='Roles and users who can bypass this filter.', size=None, validators=[pydis_site.apps.api.models.bot.filters.validate_bypass_roles_field])),                  ('enabled', models.BooleanField(help_text='Whether this filter is currently enabled.')),                  ('dm_content', models.CharField(help_text='The DM to send to a user triggering this filter.', max_length=1000, null=True)),                  ('infraction_type', models.CharField(choices=[('note', 'Note'), ('warning', 'Warning'), ('watch', 'Watch'), ('mute', 'Mute'), ('kick', 'Kick'), ('ban', 'Ban'), ('superstar', 'Superstar'), ('voice_ban', 'Voice Ban')], help_text='The infraction to apply to this user.', max_length=9, null=True)), diff --git a/pydis_site/apps/api/migrations/0075_prepare_filter_and_filterlist_for_new_filter_schema.py b/pydis_site/apps/api/migrations/0075_prepare_filter_and_filterlist_for_new_filter_schema.py index 30537e3d..cc524fcb 100644 --- a/pydis_site/apps/api/migrations/0075_prepare_filter_and_filterlist_for_new_filter_schema.py +++ b/pydis_site/apps/api/migrations/0075_prepare_filter_and_filterlist_for_new_filter_schema.py @@ -10,12 +10,26 @@ def migrate_filterlist(apps: Apps, schema_editor: BaseDatabaseSchemaEditor) -> N          "filter_token": "tokens",          "domain_name": "domains",          "guild_invite": "invites", -        "file_format": "formats" +        "file_format": "extensions"      }      for filter_list in FilterList.objects.all():          if change_map.get(filter_list.name):              filter_list.name = change_map.get(filter_list.name)              filter_list.save() +    redirects = FilterList( +        name="redirects", +        ping_type=[], +        dm_ping_type=[], +        enabled_channels=[], +        disabled_channels=[], +        disabled_categories=[], +        list_type=0, +        filter_dm=True, +        delete_messages=False, +        bypass_roles=[0], +        enabled=True +    ) +    redirects.save()  def unmigrate_filterlist(apps: Apps, schema_editor: BaseDatabaseSchemaEditor) -> None: @@ -30,6 +44,7 @@ def unmigrate_filterlist(apps: Apps, schema_editor: BaseDatabaseSchemaEditor) ->          if change_map.get(filter_list.name):              filter_list.name = change_map.get(filter_list.name)              filter_list.save() +    FilterList.objects.filter(name="redirects").delete()  class Migration(migrations.Migration): diff --git a/pydis_site/apps/api/migrations/0078_merge_20211218_2200.py b/pydis_site/apps/api/migrations/0078_merge_20211218_2200.py new file mode 100644 index 00000000..7fe559f5 --- /dev/null +++ b/pydis_site/apps/api/migrations/0078_merge_20211218_2200.py @@ -0,0 +1,14 @@ +# Generated by Django 3.1.14 on 2021-12-18 22:00 + +from django.db import migrations + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('api', '0075_prepare_filter_and_filterlist_for_new_filter_schema'), +        ('api', '0077_use_generic_jsonfield'), +    ] + +    operations = [ +    ] diff --git a/pydis_site/apps/api/migrations/0079_add_server_message_and_alert_fields.py b/pydis_site/apps/api/migrations/0079_add_server_message_and_alert_fields.py new file mode 100644 index 00000000..f9803bd3 --- /dev/null +++ b/pydis_site/apps/api/migrations/0079_add_server_message_and_alert_fields.py @@ -0,0 +1,69 @@ +# Generated by Django 3.1.14 on 2021-12-19 23:05 +from django.apps.registry import Apps +from django.db import migrations, models +from django.db.backends.base.schema import BaseDatabaseSchemaEditor + + +def migrate_filterlist(apps: Apps, schema_editor: BaseDatabaseSchemaEditor) -> None: +    FilterList = apps.get_model("api", "FilterList") +    change_map = { +        "tokens": True, +        "domains": True, +        "invites": True, +        "extensions": False, +        "redirects": False +    } +    for filter_list in FilterList.objects.all(): +        filter_list.send_alert = change_map.get(filter_list.name) +        filter_list.server_message_text = "" +        filter_list.server_message_embed = "" +        filter_list.save() + + +def unmigrate_filterlist(apps: Apps, schema_editor: BaseDatabaseSchemaEditor) -> None: +    FilterList = apps.get_model("api", "FilterList") +    for filter_list in FilterList.objects.all(): +        filter_list.send_alert = True +        filter_list.server_message_text = None +        filter_list.server_message_embed = None +        filter_list.save() + + +class Migration(migrations.Migration): +    dependencies = [ +        ('api', '0078_merge_20211218_2200'), +    ] + +    operations = [ +        migrations.AddField( +            model_name='filter', +            name='send_alert', +            field=models.BooleanField(help_text='Whether alert should be sent.', null=True), +        ), +        migrations.AddField( +            model_name='filter', +            name='server_message_embed', +            field=models.CharField(help_text='The content of the server message embed', max_length=100, null=True), +        ), +        migrations.AddField( +            model_name='filter', +            name='server_message_text', +            field=models.CharField(help_text='The message to send on the server', max_length=100, null=True), +        ), +        migrations.AddField( +            model_name='filterlist', +            name='send_alert', +            field=models.BooleanField(default=True, help_text='Whether alert should be sent.'), +        ), +        migrations.AddField( +            model_name='filterlist', +            name='server_message_embed', +            field=models.CharField(help_text='The content of the server message embed', max_length=100, null=True), +        ), +        migrations.AddField( +            model_name='filterlist', +            name='server_message_text', +            field=models.CharField(help_text='The message to send on the server', max_length=100, null=True), +        ), +        migrations.RunPython(migrate_filterlist, unmigrate_filterlist) +    ] diff --git a/pydis_site/apps/api/models/bot/filters.py b/pydis_site/apps/api/models/bot/filters.py index ae877685..92251ee4 100644 --- a/pydis_site/apps/api/models/bot/filters.py +++ b/pydis_site/apps/api/models/bot/filters.py @@ -18,6 +18,7 @@ class FilterListType(models.IntegerChoices):  # Valid special values in ping related fields  VALID_PINGS = ("everyone", "here", "moderators", "onduty", "admins") +VALID_BYPASS_ROLES = ("staff",)  def validate_ping_field(value_list: List[str]) -> None: @@ -33,6 +34,14 @@ def validate_ping_field(value_list: List[str]) -> None:          raise ValidationError(f"{value!r} isn't a valid ping type.") +def validate_bypass_roles_field(value_list: List[str]) -> None: +    """Validate that the vclues are either a special value or a Role ID.""" +    for value in value_list: +        if value.isnumeric() or value in VALID_BYPASS_ROLES: +            continue +        raise ValidationError(f"{value!r} isn't a valid (bypass) role.") + +  class FilterSettingsMixin(models.Model):      """Mixin for common settings of a filters and filter lists.""" @@ -88,14 +97,30 @@ class FilterList(FilterSettingsMixin):          null=False      )      bypass_roles = ArrayField( -        models.BigIntegerField(), +        models.CharField(max_length=100),          help_text="Roles and users who can bypass this filter.", +        validators=(validate_bypass_roles_field,),          null=False      )      enabled = models.BooleanField(          help_text="Whether this filter is currently enabled.",          null=False      ) +    send_alert = models.BooleanField( +        help_text="Whether alert should be sent.", +        null=False, +        default=True +    ) +    server_message_text = models.CharField( +        max_length=100, +        help_text="The message to send on the server", +        null=True +    ) +    server_message_embed = models.CharField( +        max_length=100, +        help_text="The content of the server message embed", +        null=True +    )      # Where a filter should apply.      #      # The resolution is done in the following order: @@ -145,14 +170,29 @@ class Filter(FilterSettingsMixin):          null=True      )      bypass_roles = ArrayField( -        models.BigIntegerField(), +        models.CharField(max_length=100),          help_text="Roles and users who can bypass this filter.", +        validators=(validate_bypass_roles_field,),          null=True      )      enabled = models.BooleanField(          help_text="Whether this filter is currently enabled.",          null=True      ) +    send_alert = models.BooleanField( +        help_text="Whether alert should be sent.", +        null=True +    ) +    server_message_text = models.CharField( +        max_length=100, +        help_text="The message to send on the server", +        null=True +    ) +    server_message_embed = models.CharField( +        max_length=100, +        help_text="The content of the server message embed", +        null=True +    )      # Check FilterList model for information about these properties.      enabled_channels = ArrayField(models.IntegerField(), null=True) diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index 784f8160..30af9512 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -139,7 +139,8 @@ BASE_SETTINGS_FIELDS = (      "bypass_roles",      "filter_dm",      "enabled", -    "delete_messages" +    "delete_messages", +    "send_alert"  )  INFRACTION_FIELDS = ("infraction_type", "infraction_reason", "infraction_duration")  CHANNEL_SCOPE_FIELDS = ( @@ -147,6 +148,7 @@ CHANNEL_SCOPE_FIELDS = (      "disabled_categories",      "enabled_channels",  ) +SERVER_MESSAGE_FIELDS = ("server_message_text", "server_message_embed")  MENTIONS_FIELDS = ("ping_type", "dm_ping_type")  SETTINGS_FIELDS = ALWAYS_OPTIONAL_SETTINGS + REQUIRED_FOR_FILTER_LIST_SETTINGS @@ -214,10 +216,16 @@ class FilterSerializer(ModelSerializer):                      "mentions":                          {                              schema_field_name: getattr(instance, schema_field_name) -                            for schema_field_name in MENTIONS_FIELDS} +                            for schema_field_name in MENTIONS_FIELDS +                        }                  } +        } | { +            "server_message": +            { +                schema_field_name: getattr(instance, schema_field_name) +                for schema_field_name in SERVER_MESSAGE_FIELDS +            }          } -          schema_base = {name: getattr(instance, name) for name in BASE_FILTER_FIELDS} | \                        {"filter_list": instance.filter_list.id} @@ -307,6 +315,11 @@ class FilterListSerializer(ModelSerializer):                  schema_field_name: getattr(instance, schema_field_name)                  for schema_field_name in MENTIONS_FIELDS              } +        } | { +            "server_message": { +                schema_field_name: getattr(instance, schema_field_name) +                for schema_field_name in SERVER_MESSAGE_FIELDS +            }          }          return schema_base | {"settings": schema_settings_base | schema_settings_categories} diff --git a/pydis_site/apps/api/viewsets/bot/filters.py b/pydis_site/apps/api/viewsets/bot/filters.py index 20af079d..e52cd4e5 100644 --- a/pydis_site/apps/api/viewsets/bot/filters.py +++ b/pydis_site/apps/api/viewsets/bot/filters.py @@ -22,20 +22,21 @@ class FilterListViewSet(ModelViewSet):      >>> [      ...     {      ...         "id": 1, -    ...         "name": "guild_invite", +    ...         "name": "invites",      ...         "list_type": 1,      ...         "filters": [      ...             {      ...                 "id": 1, -    ...                 "filter_list": 1      ...                 "content": "267624335836053506",      ...                 "description": "Python Discord",      ...                 "additional_field": None, +    ...                 "filter_list": 1      ...                 "settings": {      ...                        "bypass_roles": None      ...                        "filter_dm": None, -    ...                        "enabled": False -    ...                        "delete_messages": True +    ...                        "enabled": None +    ...                        "send_alert": True, +    ...                        "delete_messages": None      ...                        "infraction": {      ...                            "infraction_type": None,      ...                            "infraction_reason": "", @@ -50,37 +51,42 @@ class FilterListViewSet(ModelViewSet):      ...                            "ping_type": None      ...                            "dm_ping_type": None      ...                         } +    ...                        "server_message": { +    ...                            "server_message_text": None, +    ...                            "server_message_embed": None +    ...                        }      ...                    }      ...      ...             },      ...             ...      ...         ],      ...            "settings": { -    ...              "ping_type": [ -    ...                  "onduty" -    ...              ], -    ...              "dm_ping_type": [ -    ...                  "onduty" -    ...              ],      ...              "bypass_roles": [ -    ...                  267630620367257601 +    ...                  "staff"      ...              ],      ...              "filter_dm": True, -    ...              "enabled": False -    ...              "delete_messages": True +    ...              "enabled": True +    ...              "delete_messages": True, +    ...              "send_alert": True      ...              "infraction": { -    ...                   "infraction_type": None, +    ...                   "infraction_type": "",      ...                   "infraction_reason": "", -    ...                   "infraction_duration": None, +    ...                   "infraction_duration": "0.0",      ...               }      ...               "channel_scope": { -    ...                 "disabled_channels": None, -    ...                 "disabled_categories": None, -    ...                 "enabled_channels": None -    ...                } +    ...                 "disabled_channels": [], +    ...                 "disabled_categories": [], +    ...                 "enabled_channels": [] +    ...               }      ...               "mentions": { -    ...                 "ping_type": None -    ...                 "dm_ping_type": None +    ...                 "ping_type": [ +    ...                     "onduty" +    ...                 ] +    ...                 "dm_ping_type": [] +    ...                } +    ...                "server_message": { +    ...                 "server_message_text": "", +    ...                 "server_message_embed": ""      ...                }      ...           },      ...     ... @@ -96,7 +102,7 @@ class FilterListViewSet(ModelViewSet):      #### Response format      >>> {      ...         "id": 1, -    ...         "name": "guild_invite", +    ...         "name": "invites",      ...         "list_type": 1,      ...         "filters": [      ...             { @@ -108,8 +114,9 @@ class FilterListViewSet(ModelViewSet):      ...                 "settings": {      ...                        "bypass_roles": None      ...                        "filter_dm": None, -    ...                        "enabled": False -    ...                        "delete_messages": True +    ...                        "enabled": None +    ...                        "delete_messages": None, +    ...                        "send_alert": None      ...                        "infraction": {      ...                            "infraction_type": None,      ...                            "infraction_reason": "", @@ -124,37 +131,42 @@ class FilterListViewSet(ModelViewSet):      ...                            "ping_type": None      ...                            "dm_ping_type": None      ...                         } +    ...                         "server_message": { +    ...                             "server_message_text": None, +    ...                             "server_message_embed": None +    ...                         }      ...                    }      ...      ...             },      ...             ...      ...         ],      ...            "settings": { -    ...              "ping_type": [ -    ...                  "onduty" -    ...              ], -    ...              "dm_ping_type": [ -    ...                  "onduty" -    ...              ],      ...              "bypass_roles": [ -    ...                  267630620367257601 +    ...                  "staff"      ...              ],      ...              "filter_dm": True, -    ...              "enabled": False +    ...              "enabled": True      ...              "delete_messages": True +    ...              "send_alert": True      ...              "infraction": { -    ...                   "infraction_type": None, +    ...                   "infraction_type": "",      ...                   "infraction_reason": "", -    ...                   "infraction_duration": None, +    ...                   "infraction_duration": "0.0",      ...               }      ...               "channel_scope": { -    ...                 "disabled_channels": None, -    ...                 "disabled_categories": None, -    ...                 "enabled_channels": None +    ...                 "disabled_channels": [], +    ...                 "disabled_categories": [], +    ...                 "enabled_channels": []      ...                }      ...               "mentions": { -    ...                 "ping_type": None -    ...                 "dm_ping_type": None +    ...                 "ping_type": [ +    ...                     "onduty" +    ...                 ] +    ...                 "dm_ping_type": [] +    ...                } +    ...               "server_message": { +    ...                 "server_message_text": "", +    ...                 "server_message_embed": ""      ...                }      ... } @@ -193,11 +205,12 @@ class FilterViewSet(ModelViewSet):      ...                 "settings": {      ...                        "bypass_roles": None      ...                        "filter_dm": None, -    ...                        "enabled": False -    ...                        "delete_messages": True +    ...                        "enabled": None +    ...                        "delete_messages": True, +    ...                        "send_alert": True      ...                        "infraction": {      ...                            "infraction_type": None, -    ...                            "infraction_reason": "", +    ...                            "infraction_reason": None,      ...                            "infraction_duration": None      ...                        },      ...                        "channel_scope": { @@ -231,11 +244,12 @@ class FilterViewSet(ModelViewSet):      ...                 "settings": {      ...                        "bypass_roles": None      ...                        "filter_dm": None, -    ...                        "enabled": False -    ...                        "delete_messages": True +    ...                        "enabled": None +    ...                        "delete_messages": True, +    ...                        "send_alert": True      ...                        "infraction": {      ...                            "infraction_type": None, -    ...                            "infraction_reason": "", +    ...                            "infraction_reason": None,      ...                            "infraction_duration": None      ...                        },      ...                        "channel_scope": {  |