-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchannels.py
343 lines (280 loc) · 11.4 KB
/
channels.py
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
from __future__ import annotations
from time import mktime
from typing import Optional, List
from dateutil.parser import parse as dparse
from pydantic import BaseModel, validator, Field
from ..utils import makeEmbedError
from ...yepcord.enums import ChannelType
from ...yepcord.errors import EmbedErr, InvalidDataErr, Errors
from ...yepcord.utils import validImage, getImage
class ChannelUpdate(BaseModel):
icon: Optional[str] = "" # Only for GROUP_DM channel
owner_id: Optional[int] = Field(default=None, alias="owner") # Only for GROUP_DM channel
name: Optional[str] = None # For any channel (except DM)
# For guild channels:
type: Optional[int] = None
position: Optional[int] = None
topic: Optional[str] = None
nsfw: Optional[bool] = None
rate_limit: Optional[int] = Field(default=None, alias="rate_limit_per_user")
bitrate: Optional[int] = None
user_limit: Optional[int] = None
#permission_overwrites: List[PermissionOverwriteModel] = []
parent_id: Optional[int] = None
#rtc_region: Optional[str] = None
video_quality_mode: Optional[int] = None
default_auto_archive: Optional[int] = Field(default=None, alias="default_auto_archive_duration")
flags: Optional[int] = None
# Only for threads:
auto_archive_duration: Optional[int] = None
locked: Optional[bool] = None
invitable: Optional[bool] = None
class Config:
allow_population_by_field_name = True
@validator("name")
def validate_name(cls, value: Optional[str]):
if value is not None:
value = value[:100]
return value
@validator("icon")
def validate_icon(cls, value: Optional[str]):
if value is not None:
if not (img := getImage(value)) or not validImage(img):
value = None
return value
@validator("topic")
def validate_topic(cls, value: Optional[str]):
if value is not None:
value = value[:1024]
return value
@validator("rate_limit")
def validate_rate_limit(cls, value: Optional[int]):
if value is not None:
if value < 0: value = 0
if value > 21600: value = 21600
return value
@validator("bitrate")
def validate_bitrate(cls, value: Optional[int]):
if value is not None:
if value < 8000: value = 8000
return value
@validator("user_limit")
def validate_user_limit(cls, value: Optional[int]):
if value is not None:
if value < 0: value = 0
if value > 99: value = 99
return value
@validator("video_quality_mode")
def validate_video_quality_mode(cls, value: Optional[int]):
if value is not None:
if value not in (0, 1): value = None
return value
@validator("default_auto_archive", allow_reuse=True)
@validator("auto_archive_duration", allow_reuse=True)
def validate_video_quality_mode(cls, value: Optional[int]):
ALLOWED_DURATIONS = (60, 1440, 4320, 10080)
if value is not None:
if value not in ALLOWED_DURATIONS:
value = min(ALLOWED_DURATIONS, key=lambda x: abs(x - value)) # Take closest
return value
def to_json(self, channel_type: int) -> dict:
if channel_type == ChannelType.GROUP_DM:
return self.dict(include={"name", "icon", "owner_id"}, exclude_defaults=True)
elif channel_type == ChannelType.GUILD_CATEGORY:
return self.dict(include={"name", "position"}, exclude_defaults=True)
elif channel_type == ChannelType.GUILD_TEXT:
return self.dict(
# TODO: add `type` when GUILD_NEWS channels will be added
include={"name", "position", "topic", "nsfw", "rate_limit", "parent_id", "default_auto_archive"},
exclude_defaults=True)
elif channel_type == ChannelType.GUILD_VOICE:
return self.dict(include={"name", "position", "nsfw", "bitrate", "user_limit", "parent_id",
"video_quality_mode"}, exclude_defaults=True)
class PermissionOverwriteModel(BaseModel):
id: int
type: int
allow: int
deny: int
def dict(self, *args, **kwargs) -> dict:
kwargs["include"] = {"type", "allow", "deny"}
return super().dict(*args, **kwargs)
class EmbedFooter(BaseModel):
text: Optional[str] = None
icon_url: Optional[str] = None
@validator("text")
def validate_text(cls, value: Optional[str]):
if value is not None:
if len(value) > 2048:
raise EmbedErr(makeEmbedError(27, f"footer.text", {"length": "2048"}))
return value
@validator("icon_url")
def validate_icon_url(cls, value: Optional[str]):
if value is not None:
if (scheme := value.split(":")[0]) not in ["http", "https"]:
raise EmbedErr(makeEmbedError(24, f"footer.icon_url", {"scheme": scheme}))
return value
def dict(self, *args, **kwargs) -> dict:
kwargs["exclude_defaults"] = True
return super().dict(*args, **kwargs)
class EmbedImage(BaseModel):
url: Optional[str] = None
width: Optional[int] = None
height: Optional[int] = None
@validator("url")
def validate_url(cls, value: Optional[str]):
if value is not None:
if (scheme := value.split(":")[0]) not in ["http", "https"]:
raise EmbedErr(makeEmbedError(24, f"url", {"scheme": scheme}))
return value
def dict(self, *args, **kwargs) -> dict:
kwargs["exclude_defaults"] = True
return super().dict(*args, **kwargs)
class EmbedAuthor(BaseModel):
name: Optional[str] = None
url: Optional[str] = None
icon_url: Optional[int] = None
@validator("name")
def validate_name(cls, value: Optional[str]):
if value is not None:
if len(value) > 256:
raise EmbedErr(makeEmbedError(27, f"author.name", {"length": "256"}))
return value
@validator("url", allow_reuse=True)
@validator("icon_url", allow_reuse=True)
def validate_url(cls, value: Optional[str]):
if value is not None:
if (scheme := value.split(":")[0]) not in ["http", "https"]:
raise EmbedErr(makeEmbedError(24, f"url", {"scheme": scheme}))
return value
def dict(self, *args, **kwargs) -> dict:
kwargs["exclude_defaults"] = True
return super().dict(*args, **kwargs)
class EmbedField(BaseModel):
name: Optional[str] = None
value: Optional[str] = None
@validator("name")
def validate_name(cls, value: Optional[str]):
if not value:
raise EmbedErr(makeEmbedError(23, f"fields.name"))
if len(value) > 256:
raise EmbedErr(makeEmbedError(27, f"fields.name", {"length": "256"}))
@validator("value")
def validate_value(cls, value: Optional[str]):
if not value:
raise EmbedErr(makeEmbedError(23, f"fields.value"))
if len(value) > 1024:
raise EmbedErr(makeEmbedError(27, f"fields.value", {"length": "1024"}))
class EmbedModel(BaseModel):
title: str
type: Optional[str] = None
description: Optional[str] = None
url: Optional[str] = None
timestamp: Optional[str] = None
color: Optional[int] = None
footer: Optional[EmbedFooter] = None
image: Optional[EmbedImage] = None
thumbnail: Optional[EmbedImage] = None
video: Optional[EmbedImage] = None
author: Optional[EmbedAuthor] = None
fields: List[EmbedField] = Field(default_factory=list)
@validator("title")
def validate_title(cls, value: str):
if not value: raise EmbedErr(makeEmbedError(23))
if len(value) > 256:
raise EmbedErr(makeEmbedError(27, f"title", {"length": "256"}))
return value
@validator("type")
def validate_type(cls, value: Optional[str]):
return "rich"
@validator("description")
def validate_description(cls, value: Optional[str]):
if value is not None:
if len(value) > 4096:
raise EmbedErr(makeEmbedError(27, f"description", {"length": "4096"}))
return value
@validator("url")
def validate_url(cls, value: Optional[str]):
if value is not None:
if (scheme := value.split(":")[0]) not in ["http", "https"]:
raise EmbedErr(makeEmbedError(24, f"url", {"scheme": scheme}))
return value
@validator("timestamp")
def validate_timestamp(cls, value: Optional[str]):
if value is not None:
try:
mktime(dparse(value).timetuple())
except ValueError:
raise EmbedErr(makeEmbedError(25, f"timestamp", {"value": value}))
return value
@validator("color")
def validate_color(cls, value: Optional[int]):
if value is not None:
if value > 0xffffff or value < 0:
raise EmbedErr(makeEmbedError(26, f"color"))
return value
@validator("footer")
def validate_footer(cls, value: Optional[EmbedFooter]):
if value is not None:
if not value.text:
value = None
return value
@validator("image", allow_reuse=True)
@validator("thumbnail", allow_reuse=True)
@validator("video", allow_reuse=True)
def validate_image(cls, value: Optional[EmbedImage]):
if value is not None:
if not value.url:
value = None
return value
@validator("author")
def validate_author(cls, value: Optional[EmbedAuthor]):
if value is not None:
if not value.name:
value = None
return value
@validator("fields")
def validate_fields(cls, value: List[EmbedField]):
if len(value) > 25:
value = value[:25]
def dict(self, *args, **kwargs) -> dict:
kwargs["exclude_defaults"] = True
return super().dict(*args, **kwargs)
class MessageCreate(BaseModel):
content: Optional[str] = None
nonce: Optional[str] = None
embeds: List[EmbedModel] = Field(default_factory=list)
message_reference: Optional[int] = None
flags: Optional[int] = None
def __init__(self, **data):
if "message_reference" in data:
data["message_reference"] = data["message_reference"]["message_id"]
super().__init__(**data)
@validator("content")
def validate_content(cls, value: Optional[str]):
if value is not None:
if len(value) > 2000: value = value[:2000] # TODO: raise exception instead
return value
def to_json(self) -> dict:
return self.dict(exclude_defaults=True)
class MessageUpdate(BaseModel):
content: Optional[str] = None
embeds: List[EmbedModel] = Field(default_factory=list)
@validator("content")
def validate_content(cls, value: Optional[str]):
if value is not None:
if len(value) > 2000: value = value[:2000] # TODO: raise exception instead
return value
def to_json(self) -> dict:
return self.dict(exclude_defaults=True)
class InviteCreate(BaseModel):
max_age: Optional[int] = 86400
max_uses: Optional[int] = 0
class WebhookCreate(BaseModel):
name: Optional[str] = None
@validator("name")
def validate_name(cls, value: Optional[str]):
if not value:
raise InvalidDataErr(400,
Errors.make(50035,
{"name": {"code": "BASE_TYPE_REQUIRED", "message": "Required field"}}))
return value