1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
from collections.abc import Mapping
from django.core.exceptions import ValidationError
from django.core.validators import MaxLengthValidator, MinLengthValidator
def validate_tag_embed_fields(fields):
field_validators = {
'name': (MaxLengthValidator(limit_value=256),),
'value': (MaxLengthValidator(limit_value=1024),)
}
for field in fields:
if not isinstance(field, Mapping):
raise ValidationError("Embed fields must be a mapping.")
for field_name, value in field.items():
if field_name not in field_validators:
raise ValidationError(f"Unknown embed field field: {field_name!r}.")
for validator in field_validators[field_name]:
validator(value)
def validate_tag_embed_footer(footer):
field_validators = {
'text': (
MinLengthValidator(
limit_value=1,
message="Footer text must not be empty."
),
MaxLengthValidator(limit_value=2048)
),
'icon_url': (),
'proxy_icon_url': ()
}
if not isinstance(footer, Mapping):
raise ValidationError("Embed footer must be a mapping.")
for field_name, value in footer.items():
if field_name not in field_validators:
raise ValidationError(f"Unknown embed footer field: {field_name!r}.")
for validator in field_validators[field_name]:
validator(value)
def validate_tag_embed_author(author):
field_validators = {
'name': (
MinLengthValidator(
limit_value=1,
message="Embed author name must not be empty."
),
MaxLengthValidator(limit_value=256)
),
'url': (),
'icon_url': (),
'proxy_icon_url': ()
}
if not isinstance(author, Mapping):
raise ValidationError("Embed author must be a mapping.")
for field_name, value in author.items():
if field_name not in field_validators:
raise ValidationError(f"Unknown embed author field: {field_name!r}.")
for validator in field_validators[field_name]:
validator(value)
def validate_tag_embed(embed):
"""
Validate a JSON document containing an embed as possible to send
on Discord. This attempts to rebuild the validation used by Discord
as well as possible by checking for various embed limits so we can
ensure that any embed we store here will also be accepted as a
valid embed by the Discord API.
Using this directly is possible, although not intended - you usually
stick this onto the `validators` keyword argument of model fields.
Example:
>>> from django.contrib.postgres import fields as pgfields
>>> from django.db import models
>>> from pydis_site.apps.api import validate_tag_embed
>>> class MyMessage(models.Model):
... embed = pgfields.JSONField(
... validators=(
... validate_tag_embed,
... )
... )
... # ...
...
Args:
embed (Dict[str, Union[str, List[dict], dict]]):
A dictionary describing the contents of this embed.
See the official documentation for a full reference
of accepted keys by this dictionary:
https://discordapp.com/developers/docs/resources/channel#embed-object
Raises:
ValidationError:
In case the given embed is deemed invalid, a `ValidationError`
is raised which in turn will allow Django to display errors
as appropriate.
"""
all_keys = {
'title', 'type', 'description', 'url', 'timestamp',
'color', 'footer', 'image', 'thumbnail', 'video',
'provider', 'author', 'fields'
}
one_required_of = {'description', 'fields', 'image', 'title', 'video'}
field_validators = {
'title': (
MinLengthValidator(
limit_value=1,
message="Embed title must not be empty."
),
MaxLengthValidator(limit_value=256)
),
'description': (MaxLengthValidator(limit_value=2048),),
'fields': (
MaxLengthValidator(limit_value=25),
validate_tag_embed_fields
),
'footer': (validate_tag_embed_footer,),
'author': (validate_tag_embed_author,)
}
if not embed:
raise ValidationError("Tag embed must not be empty.")
elif not isinstance(embed, Mapping):
raise ValidationError("Tag embed must be a mapping.")
elif not any(field in embed for field in one_required_of):
raise ValidationError(f"Tag embed must contain one of the fields {one_required_of}.")
for required_key in one_required_of:
if required_key in embed and not embed[required_key]:
raise ValidationError(f"Key {required_key!r} must not be empty.")
for field_name, value in embed.items():
if field_name not in all_keys:
raise ValidationError(f"Unknown field name: {field_name!r}")
if field_name in field_validators:
for validator in field_validators[field_name]:
validator(value)
def validate_bot_setting_name(name):
KNOWN_SETTINGS = (
'defcon',
)
if name not in KNOWN_SETTINGS:
raise ValidationError(f"`{name}` is not a known setting name.")
|