scurrypy 0.4.2__py3-none-any.whl → 0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of scurrypy might be problematic. Click here for more details.
- discord/__init__.py +219 -66
- discord/dispatch/command_dispatcher.py +10 -2
- discord/events/channel_events.py +1 -1
- discord/events/interaction_events.py +19 -7
- discord/http.py +1 -1
- discord/models/emoji.py +1 -1
- discord/models/interaction.py +5 -0
- discord/parts/channel.py +24 -2
- discord/parts/command.py +45 -57
- discord/parts/components.py +224 -0
- discord/parts/components_v2.py +77 -286
- discord/parts/embed.py +38 -109
- discord/parts/message.py +46 -103
- discord/parts/modal.py +9 -14
- discord/parts/role.py +1 -13
- discord/resources/channel.py +4 -4
- discord/resources/guild.py +0 -1
- discord/resources/interaction.py +20 -19
- discord/resources/message.py +10 -10
- {scurrypy-0.4.2.dist-info → scurrypy-0.5.dist-info}/METADATA +6 -13
- {scurrypy-0.4.2.dist-info → scurrypy-0.5.dist-info}/RECORD +24 -24
- discord/parts/action_row.py +0 -208
- {scurrypy-0.4.2.dist-info → scurrypy-0.5.dist-info}/WHEEL +0 -0
- {scurrypy-0.4.2.dist-info → scurrypy-0.5.dist-info}/licenses/LICENSE +0 -0
- {scurrypy-0.4.2.dist-info → scurrypy-0.5.dist-info}/top_level.txt +0 -0
discord/parts/components_v2.py
CHANGED
|
@@ -1,131 +1,57 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional
|
|
3
3
|
from ..model import DataModel
|
|
4
4
|
|
|
5
5
|
from .component_types import *
|
|
6
|
-
from ..models.emoji import EmojiModel
|
|
7
|
-
|
|
8
|
-
from .action_row import (
|
|
9
|
-
StringSelect,
|
|
10
|
-
ActionRow,
|
|
11
|
-
ChannelSelect,
|
|
12
|
-
MentionableSelect,
|
|
13
|
-
RoleSelect,
|
|
14
|
-
UserSelect,
|
|
15
|
-
_Button,
|
|
16
|
-
_ButtonStyles
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
class _TextInputStyles:
|
|
20
|
-
"""Represents the types of Text Inputs."""
|
|
21
|
-
SHORT = 1 # one line
|
|
22
|
-
PARAGRAPH = 2 # multiple lines
|
|
23
6
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
value: Optional[str] = None
|
|
34
|
-
placeholder: Optional[str] = None
|
|
7
|
+
class ComponentV2Types:
|
|
8
|
+
SECTION = 9
|
|
9
|
+
TEXT_DISPLAY = 10
|
|
10
|
+
THUMBNAIL = 11
|
|
11
|
+
MEDIA_GALLERY = 12
|
|
12
|
+
FILE = 13
|
|
13
|
+
SEPARATOR = 14
|
|
14
|
+
CONTAINER = 17
|
|
15
|
+
LABEL = 18
|
|
35
16
|
|
|
36
17
|
@dataclass
|
|
37
|
-
class
|
|
18
|
+
class SectionPart(DataModel, ContainerChild):
|
|
38
19
|
"""Represents the Section component."""
|
|
39
|
-
type: Literal[9] = field(init=False, default=9)
|
|
40
20
|
|
|
41
21
|
accessory: Optional[SectionAccessory] = None
|
|
42
22
|
"""A component that is contextually associated to the content of the section."""
|
|
43
23
|
|
|
44
24
|
components: list[SectionChild] = field(default_factory=list)
|
|
45
|
-
"""Component(s) representing the content of the section that is contextually associated to the accessory"""
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
media (str): Image data. http or attachment://<filename> scheme.
|
|
52
|
-
description (str, optional): Alt text for the media
|
|
53
|
-
has_spoiler (bool, optional): If the media should be blurred out. Defaults to False.
|
|
54
|
-
|
|
55
|
-
Returns:
|
|
56
|
-
(Section): self
|
|
57
|
-
"""
|
|
58
|
-
self.accessory = _Thumbnail(media, description, has_spoiler)
|
|
59
|
-
return self
|
|
60
|
-
|
|
61
|
-
def add_text_display(self, content: str):
|
|
62
|
-
"""Add a text display to this section.
|
|
63
|
-
|
|
64
|
-
Args:
|
|
65
|
-
content (str): the content to display
|
|
66
|
-
|
|
67
|
-
Returns:
|
|
68
|
-
(Section): self
|
|
69
|
-
"""
|
|
70
|
-
self.components.append(_TextDisplay(content))
|
|
71
|
-
return self
|
|
72
|
-
|
|
73
|
-
def set_button(self,
|
|
74
|
-
*,
|
|
75
|
-
style: Literal['Primary', 'Secondary', 'Success', 'Danger', 'Link'],
|
|
76
|
-
label: str,
|
|
77
|
-
custom_id: str,
|
|
78
|
-
emoji: str | EmojiModel = None,
|
|
79
|
-
disable: bool = False
|
|
80
|
-
):
|
|
81
|
-
"""Set this section's accessory as a button.
|
|
82
|
-
|
|
83
|
-
Args:
|
|
84
|
-
style (Literal['Primary', 'Secondary', 'Success', 'Danger', 'Link']):
|
|
85
|
-
button style as a string
|
|
86
|
-
label (str): button text
|
|
87
|
-
custom_id (str): developer-defined button ID
|
|
88
|
-
emoji (str | EmojiModel, Optional): str if unicode emoji, EmojiModal if custom
|
|
89
|
-
disable (bool, Optional): if this button should be pressable. Defaults to False.
|
|
90
|
-
|
|
91
|
-
Returns:
|
|
92
|
-
(Section): self
|
|
93
|
-
"""
|
|
94
|
-
_styles = {
|
|
95
|
-
'PRIMARY': _ButtonStyles.PRIMARY,
|
|
96
|
-
'SECONDARY': _ButtonStyles.SECONDARY,
|
|
97
|
-
'SUCCESS': _ButtonStyles.SUCCESS,
|
|
98
|
-
'DANGER': _ButtonStyles.DANGER,
|
|
99
|
-
'LINK': _ButtonStyles.LINK
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if isinstance(emoji, str):
|
|
103
|
-
emoji = EmojiModel(name=emoji)
|
|
104
|
-
|
|
105
|
-
self.accessory = _Button(
|
|
106
|
-
style=_styles.get(style.upper()),
|
|
107
|
-
label=label,
|
|
108
|
-
custom_id=custom_id,
|
|
109
|
-
emoji=emoji,
|
|
110
|
-
disabled=disable
|
|
111
|
-
)
|
|
112
|
-
return self
|
|
25
|
+
"""Component(s) representing the content of the section that is contextually associated to the accessory."""
|
|
26
|
+
|
|
27
|
+
type: int = field(init=False, default=ComponentV2Types.SECTION)
|
|
28
|
+
"""Component type. Always `ComponentV2Types.SECTION` for this class. See [`ComponentV2Types`][discord.parts.components_v2.ComponentV2Types]."""
|
|
113
29
|
|
|
114
30
|
@dataclass
|
|
115
|
-
class
|
|
31
|
+
class TextDisplay(DataModel, ContainerChild, SectionChild):
|
|
116
32
|
"""Represents the Text Display component."""
|
|
117
|
-
|
|
33
|
+
|
|
118
34
|
content: str
|
|
35
|
+
"""Text that will be displayed similar to a message."""
|
|
119
36
|
|
|
37
|
+
type: int = field(init=False, default=ComponentV2Types.TEXT_DISPLAY)
|
|
38
|
+
"""Component type. Always `ComponentV2Types.TEXT_DISPLAY` for this class. See [`ComponentV2Types`][discord.parts.components_v2.ComponentV2Types]."""
|
|
120
39
|
|
|
121
40
|
@dataclass
|
|
122
|
-
class
|
|
123
|
-
"""Represents the
|
|
124
|
-
|
|
125
|
-
media: str
|
|
41
|
+
class Thumbnail(DataModel, SectionAccessory):
|
|
42
|
+
"""Represents the Thumbnail component."""
|
|
43
|
+
|
|
44
|
+
media: str
|
|
45
|
+
"""Media of the thumbnail. http or attachment://<filename> scheme."""
|
|
46
|
+
|
|
126
47
|
description: Optional[str] = None
|
|
48
|
+
"""Description for the media."""
|
|
49
|
+
|
|
127
50
|
spoiler: Optional[bool] = False
|
|
51
|
+
"""Whether the thumbnail should be a spoiler (or blurred out)."""
|
|
128
52
|
|
|
53
|
+
type: int = field(init=False, default=ComponentV2Types.THUMBNAIL)
|
|
54
|
+
"""Component type. Always `ComponentV2Types.THUMBNAIL` for this class. See [`ComponentV2Types`][discord.parts.components_v2.ComponentV2Types]."""
|
|
129
55
|
|
|
130
56
|
@dataclass
|
|
131
57
|
class MediaGalleryItem(DataModel):
|
|
@@ -138,106 +64,56 @@ class MediaGalleryItem(DataModel):
|
|
|
138
64
|
"""Alt text for the media."""
|
|
139
65
|
|
|
140
66
|
spoiler: Optional[bool] = False
|
|
141
|
-
"""
|
|
67
|
+
"""Whether the thumbnail should be a spoiler (or blurred out)."""
|
|
142
68
|
|
|
143
69
|
@dataclass
|
|
144
|
-
class
|
|
70
|
+
class MediaGallery(DataModel, ContainerChild):
|
|
145
71
|
"""Represents the Media Gallery component."""
|
|
146
|
-
|
|
72
|
+
|
|
147
73
|
items: list[MediaGalleryItem] = field(default_factory=list)
|
|
74
|
+
"""1 to 10 nedia gallery items. See [`MediaGalleryItem`][discord.parts.components_v2.MediaGalleryItem]."""
|
|
148
75
|
|
|
76
|
+
type: int = field(init=False, default=ComponentV2Types.MEDIA_GALLERY)
|
|
77
|
+
"""Component type. Always `ComponentV2Types.MEDIA_GALLERY` for this class. See [`ComponentV2Types`][discord.parts.components_v2.ComponentV2Types]."""
|
|
149
78
|
|
|
150
79
|
@dataclass
|
|
151
|
-
class
|
|
80
|
+
class File(DataModel, ContainerChild):
|
|
152
81
|
"""Represents the File component."""
|
|
153
|
-
|
|
154
|
-
file: str
|
|
82
|
+
|
|
83
|
+
file: str
|
|
84
|
+
"""File name. ONLY supports attachment://<filename> scheme."""
|
|
85
|
+
|
|
155
86
|
spoiler: Optional[bool] = False
|
|
87
|
+
"""Whether the thumbnail should be a spoiler (or blurred out)."""
|
|
88
|
+
|
|
89
|
+
type: int = field(init=False, default=ComponentV2Types.FILE)
|
|
90
|
+
"""Component type. Always `ComponentV2Types.File` for this class. See [`ComponentV2Types`][discord.parts.components_v2.ComponentV2Types]."""
|
|
156
91
|
|
|
157
|
-
class
|
|
92
|
+
class SeparatorTypes:
|
|
158
93
|
"""Represents separator types constants."""
|
|
94
|
+
|
|
159
95
|
SMALL_PADDING = 1
|
|
96
|
+
"""Small separator padding."""
|
|
97
|
+
|
|
160
98
|
LARGE_PADDING = 2
|
|
99
|
+
"""Large separator padding."""
|
|
161
100
|
|
|
162
101
|
@dataclass
|
|
163
|
-
class
|
|
102
|
+
class Separator(DataModel, ContainerChild):
|
|
164
103
|
"""Represents the Separator component."""
|
|
165
|
-
type: Literal[14] = field(init=False, default=14)
|
|
166
|
-
divider: bool = True
|
|
167
|
-
spacing: Optional[int] = _SeparatorTypes.SMALL_PADDING # refer to _SeparatorTypes
|
|
168
|
-
|
|
169
|
-
@dataclass
|
|
170
|
-
class Label(DataModel):
|
|
171
|
-
"""Represents the Discord Label component."""
|
|
172
104
|
|
|
173
|
-
|
|
174
|
-
"""
|
|
175
|
-
|
|
176
|
-
component: LabelChild = None
|
|
177
|
-
"""A component within the label."""
|
|
105
|
+
divider: bool = True
|
|
106
|
+
"""Whether a visual divider should be displayed in the component. Defaults to True."""
|
|
178
107
|
|
|
179
|
-
|
|
180
|
-
"""
|
|
108
|
+
spacing: Optional[int] = SeparatorTypes.SMALL_PADDING
|
|
109
|
+
"""Size of separator padding. Defaults to `SMALL_PADDING`. See [`SeparatorTypes`][discord.parts.components_v2.SeparatorTypes]."""
|
|
181
110
|
|
|
182
|
-
type:
|
|
183
|
-
|
|
184
|
-
def set_select_menu(self, select: StringSelect | UserSelect | RoleSelect | ChannelSelect | MentionableSelect):
|
|
185
|
-
"""Set this label to be a select menu component.
|
|
186
|
-
|
|
187
|
-
Args:
|
|
188
|
-
select (StringSelect | UserSelect | RoleSelect | ChannelSelect | MentionableSelect): the select menu component
|
|
189
|
-
|
|
190
|
-
Returns:
|
|
191
|
-
(Label): self
|
|
192
|
-
"""
|
|
193
|
-
self.component = select
|
|
194
|
-
return self
|
|
195
|
-
|
|
196
|
-
def set_text_input(self,
|
|
197
|
-
*,
|
|
198
|
-
custom_id: str,
|
|
199
|
-
min_length: int,
|
|
200
|
-
max_length: int,
|
|
201
|
-
value: str = None,
|
|
202
|
-
style: Literal['Short', 'Paragraph'] = 'Short',
|
|
203
|
-
placeholder: str = None,
|
|
204
|
-
require: bool = False
|
|
205
|
-
):
|
|
206
|
-
"""Set this label to be a text input component.
|
|
207
|
-
|
|
208
|
-
Args:
|
|
209
|
-
custom_id (str): developer-defined component ID
|
|
210
|
-
min_length (int): minimum number of characters required
|
|
211
|
-
max_length (int): maximum number of characters required
|
|
212
|
-
value (str, optional): component value
|
|
213
|
-
style (Literal['Short', 'Paragraph'], optional):
|
|
214
|
-
text format. Defaults to 'Short'.
|
|
215
|
-
placeholder (str, optional): custom placeholder text if empty
|
|
216
|
-
require (bool, optional): if input is required. Defaults to False.
|
|
217
|
-
|
|
218
|
-
Returns:
|
|
219
|
-
(Label): self
|
|
220
|
-
"""
|
|
221
|
-
_styles = {
|
|
222
|
-
'SHORT': _TextInputStyles.SHORT,
|
|
223
|
-
'PARAGRAPH': _TextInputStyles.PARAGRAPH
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
self.component = _TextInput(
|
|
227
|
-
style = _styles.get(style.upper()),
|
|
228
|
-
placeholder=placeholder,
|
|
229
|
-
custom_id=custom_id,
|
|
230
|
-
min_length=min_length,
|
|
231
|
-
max_length=max_length,
|
|
232
|
-
value=value,
|
|
233
|
-
required=require
|
|
234
|
-
)
|
|
235
|
-
return self
|
|
111
|
+
type: int = field(init=False, default=ComponentV2Types.SEPARATOR)
|
|
112
|
+
"""Component type. Always `ComponentV2Types.SEPARATOR` for this class. See [`ComponentV2Types`][discord.parts.components_v2.ComponentV2Types]."""
|
|
236
113
|
|
|
237
114
|
@dataclass
|
|
238
|
-
class
|
|
115
|
+
class ContainerPart(DataModel):
|
|
239
116
|
"""Represents a container of display and interactable components."""
|
|
240
|
-
type: Literal[17] = field(init=False, default=17)
|
|
241
117
|
|
|
242
118
|
components: list[ContainerChild] = field(default_factory=list)
|
|
243
119
|
"""Child components that are encapsulated within the Container."""
|
|
@@ -246,108 +122,23 @@ class Container(DataModel):
|
|
|
246
122
|
"""Color for the accent as an integer."""
|
|
247
123
|
|
|
248
124
|
spoiler: Optional[bool] = False
|
|
249
|
-
"""If the container should be blurred out."""
|
|
250
|
-
|
|
251
|
-
def set_color(self, hex: str):
|
|
252
|
-
"""Set this container's color with a hex. (format: #FFFFFF)
|
|
253
|
-
|
|
254
|
-
Args:
|
|
255
|
-
hex (str): color as a hex code
|
|
256
|
-
|
|
257
|
-
Returns:
|
|
258
|
-
(Container): self
|
|
259
|
-
"""
|
|
260
|
-
self.accent_color = int(hex.strip('#'), 16)
|
|
261
|
-
return self
|
|
262
|
-
|
|
263
|
-
def add_row(self, row: ActionRow):
|
|
264
|
-
"""Add an action row to this container.
|
|
265
|
-
|
|
266
|
-
Args:
|
|
267
|
-
row (ActionRow): the ActionRow object
|
|
268
|
-
|
|
269
|
-
Returns:
|
|
270
|
-
(Container): self
|
|
271
|
-
"""
|
|
272
|
-
self.components.append(row)
|
|
273
|
-
return self
|
|
274
|
-
|
|
275
|
-
def add_section(self, section: Section):
|
|
276
|
-
"""Add a section to this container.
|
|
277
|
-
|
|
278
|
-
Args:
|
|
279
|
-
section (Section): the Section object
|
|
280
|
-
|
|
281
|
-
Returns:
|
|
282
|
-
(Container): self
|
|
283
|
-
"""
|
|
284
|
-
self.components.append(section)
|
|
285
|
-
return self
|
|
286
|
-
|
|
287
|
-
def add_text_display(self, content: str):
|
|
288
|
-
"""Add a text display to this container.
|
|
289
|
-
|
|
290
|
-
Args:
|
|
291
|
-
content (str): the content to display
|
|
292
|
-
|
|
293
|
-
Returns:
|
|
294
|
-
(Container): self
|
|
295
|
-
"""
|
|
296
|
-
self.components.append(_TextDisplay(content))
|
|
297
|
-
return self
|
|
298
|
-
|
|
299
|
-
def set_thumbnail(self, media: str, description: str = None, has_spoiler: bool = False):
|
|
300
|
-
"""Set the thumbnail for this container
|
|
301
|
-
|
|
302
|
-
Args:
|
|
303
|
-
media (str): Image data. http or attachment://<filename> scheme.
|
|
304
|
-
description (str, optional): Alt text for the media
|
|
305
|
-
has_spoiler (bool, optional): If the media should be blurred out. Defaults to False.
|
|
306
|
-
|
|
307
|
-
Returns:
|
|
308
|
-
(Container): self
|
|
309
|
-
"""
|
|
310
|
-
self.components.append(_Thumbnail(media, description, has_spoiler))
|
|
311
|
-
return self
|
|
312
|
-
|
|
313
|
-
def set_media_gallery(self, items: list[MediaGalleryItem]):
|
|
314
|
-
"""Add a media gallery to this container.
|
|
125
|
+
"""If the container should be blurred out. Defaults to False."""
|
|
315
126
|
|
|
316
|
-
|
|
317
|
-
|
|
127
|
+
type: int = field(init=False, default=ComponentV2Types.CONTAINER)
|
|
128
|
+
"""Component type. Always `ComponentV2Types.CONTAINER` for this class. See [`ComponentV2Types`][discord.parts.components_v2.ComponentV2Types]."""
|
|
318
129
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
"""
|
|
335
|
-
self.components.append(_File(file, has_spoiler))
|
|
336
|
-
return self
|
|
337
|
-
|
|
338
|
-
def add_separator(self, spacing: Literal['Small', 'Large'] = 'Small', has_divider: bool = True):
|
|
339
|
-
"""Add a separator to this container. Positionally accurate.
|
|
340
|
-
|
|
341
|
-
Args:
|
|
342
|
-
spacing (Literal['Small', 'Large'], optional): size of separator padding. Defaults to 'Small'.
|
|
343
|
-
has_divider (bool, optional): if a visual divider should be shown. Defaults to True.
|
|
344
|
-
|
|
345
|
-
Returns:
|
|
346
|
-
(Container): self
|
|
347
|
-
"""
|
|
348
|
-
_spacing_types = {
|
|
349
|
-
'SMALL': _SeparatorTypes.SMALL_PADDING,
|
|
350
|
-
'LARGE': _SeparatorTypes.LARGE_PADDING
|
|
351
|
-
}
|
|
352
|
-
self.components.append(_Separator(divider=has_divider, spacing=_spacing_types.get(spacing.upper())))
|
|
353
|
-
return self
|
|
130
|
+
@dataclass
|
|
131
|
+
class Label(DataModel):
|
|
132
|
+
"""Represents the Discord Label component."""
|
|
133
|
+
|
|
134
|
+
label: str
|
|
135
|
+
"""Label text."""
|
|
136
|
+
|
|
137
|
+
component: LabelChild = None
|
|
138
|
+
"""A component within the label."""
|
|
139
|
+
|
|
140
|
+
description: Optional[str] = None
|
|
141
|
+
"""An optional description text for the label."""
|
|
142
|
+
|
|
143
|
+
type: int = field(init=False, default=ComponentV2Types.LABEL)
|
|
144
|
+
"""Component type. Always `ComponentV2Types.LABEL` for this class. See [`ComponentV2Types`][discord.parts.components_v2.ComponentV2Types]."""
|
discord/parts/embed.py
CHANGED
|
@@ -1,42 +1,58 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
2
|
from typing import Optional
|
|
3
|
-
from
|
|
4
|
-
from datetime import datetime, timezone
|
|
5
|
-
from ..models.user import UserModel
|
|
3
|
+
from ..model import DataModel
|
|
6
4
|
|
|
7
5
|
@dataclass
|
|
8
|
-
class
|
|
6
|
+
class EmbedAuthor(DataModel):
|
|
9
7
|
"""Embed author parameters."""
|
|
8
|
+
|
|
10
9
|
name: str
|
|
10
|
+
"""Name of the author."""
|
|
11
|
+
|
|
11
12
|
url: Optional[str] = None
|
|
13
|
+
"""URL of the author. http or attachment://<filename> scheme."""
|
|
14
|
+
|
|
12
15
|
icon_url: Optional[str] = None
|
|
16
|
+
"""URL of author's icon. http or attachment://<filename> scheme."""
|
|
13
17
|
|
|
14
18
|
@dataclass
|
|
15
|
-
class
|
|
19
|
+
class EmbedThumbnail(DataModel):
|
|
16
20
|
"""Embed thumbnail."""
|
|
21
|
+
|
|
17
22
|
url: str
|
|
23
|
+
"""Thumbnail content. http or attachment://<filename> scheme."""
|
|
18
24
|
|
|
19
25
|
@dataclass
|
|
20
|
-
class
|
|
26
|
+
class EmbedField(DataModel):
|
|
27
|
+
"""Embed field."""
|
|
28
|
+
|
|
29
|
+
name: str
|
|
30
|
+
"""Name of the field."""
|
|
31
|
+
|
|
32
|
+
value: str
|
|
33
|
+
"""Value of the field."""
|
|
34
|
+
|
|
35
|
+
inline: Optional[bool] = None
|
|
36
|
+
"""Whether or not this field should display inline."""
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class EmbedImage(DataModel):
|
|
21
40
|
"""Embed image."""
|
|
41
|
+
|
|
22
42
|
url: str
|
|
43
|
+
"""Image content. http or attachment://<filename> scheme."""
|
|
23
44
|
|
|
24
45
|
@dataclass
|
|
25
|
-
class
|
|
46
|
+
class EmbedFooter(DataModel):
|
|
26
47
|
"""Embed footer."""
|
|
27
48
|
text: str
|
|
28
|
-
|
|
29
|
-
icon_url: Optional[str] = None
|
|
49
|
+
"""Footer text."""
|
|
30
50
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"""Embed field."""
|
|
34
|
-
name: str
|
|
35
|
-
value: str
|
|
36
|
-
inline: Optional[bool] = None
|
|
51
|
+
icon_url: Optional[str] = None
|
|
52
|
+
"""URL of the footer icon. http or attachment://<filename> scheme."""
|
|
37
53
|
|
|
38
54
|
@dataclass
|
|
39
|
-
class
|
|
55
|
+
class EmbedPart(DataModel):
|
|
40
56
|
"""Represents the Embed portion of a message."""
|
|
41
57
|
|
|
42
58
|
title: Optional[str] = None
|
|
@@ -51,104 +67,17 @@ class EmbedBuilder(DataModel):
|
|
|
51
67
|
color: Optional[int] = None
|
|
52
68
|
"""Embed's accent color."""
|
|
53
69
|
|
|
54
|
-
author: Optional[
|
|
70
|
+
author: Optional[EmbedAuthor] = None
|
|
55
71
|
"""Embed's author."""
|
|
56
72
|
|
|
57
|
-
thumbnail: Optional[
|
|
73
|
+
thumbnail: Optional[EmbedThumbnail] = None
|
|
58
74
|
"""Embed's thumbnail attachment."""
|
|
59
75
|
|
|
60
|
-
image: Optional[
|
|
76
|
+
image: Optional[EmbedImage] = None
|
|
61
77
|
"""Embed's image attachment."""
|
|
62
78
|
|
|
63
|
-
fields: Optional[list[
|
|
79
|
+
fields: Optional[list[EmbedField]] = field(default_factory=list)
|
|
64
80
|
"""List of embed's fields."""
|
|
65
81
|
|
|
66
|
-
footer: Optional[
|
|
82
|
+
footer: Optional[EmbedFooter] = None
|
|
67
83
|
"""Embed's footer."""
|
|
68
|
-
|
|
69
|
-
def set_color(self, hex: str):
|
|
70
|
-
"""Set this embed's color with a hex.
|
|
71
|
-
|
|
72
|
-
Args:
|
|
73
|
-
hex (str): color as a hex code (format: #FFFFFF)
|
|
74
|
-
|
|
75
|
-
Returns:
|
|
76
|
-
(EmbedBuilder): self
|
|
77
|
-
"""
|
|
78
|
-
self.color=int(hex.strip('#'), 16)
|
|
79
|
-
return self
|
|
80
|
-
|
|
81
|
-
def set_user_author(self, user: UserModel):
|
|
82
|
-
"""Set this embed's author.
|
|
83
|
-
|
|
84
|
-
Args:
|
|
85
|
-
user (UserModel): the user model
|
|
86
|
-
|
|
87
|
-
Returns:
|
|
88
|
-
(EmbedBuilder): self
|
|
89
|
-
"""
|
|
90
|
-
self.author = _EmbedAuthor(
|
|
91
|
-
name=user.username,
|
|
92
|
-
icon_url=f"https://cdn.discordapp.com/avatars/{user.id}/{user.avatar}.png"
|
|
93
|
-
)
|
|
94
|
-
return self
|
|
95
|
-
|
|
96
|
-
def set_image(self, url: str):
|
|
97
|
-
"""Set this embed's image.
|
|
98
|
-
|
|
99
|
-
Args:
|
|
100
|
-
url (str): attachment://<file> scheme or http(s) URL
|
|
101
|
-
|
|
102
|
-
Returns:
|
|
103
|
-
(EmbedBuilder): self
|
|
104
|
-
"""
|
|
105
|
-
self.image = _EmbedImage(url=url)
|
|
106
|
-
return self
|
|
107
|
-
|
|
108
|
-
def set_thumbnail(self, url: str):
|
|
109
|
-
"""Set this embed's thumbnail.
|
|
110
|
-
|
|
111
|
-
Args:
|
|
112
|
-
url (str): attachment://<file> scheme or http(s) URL
|
|
113
|
-
|
|
114
|
-
Returns:
|
|
115
|
-
(EmbedBuilder): self
|
|
116
|
-
"""
|
|
117
|
-
self.thumbnail = _EmbedThumbnail(url=url)
|
|
118
|
-
return self
|
|
119
|
-
|
|
120
|
-
def set_footer(self, text: str, icon_url: str = None):
|
|
121
|
-
"""Set this embed's footer.
|
|
122
|
-
|
|
123
|
-
Args:
|
|
124
|
-
text (str): footer's text
|
|
125
|
-
icon_url (str, optional): attachment://<file> scheme or http(s) URL.
|
|
126
|
-
|
|
127
|
-
Returns:
|
|
128
|
-
(EmbedBuilder): self
|
|
129
|
-
"""
|
|
130
|
-
self.footer = _EmbedFooter(text=text, icon_url=icon_url)
|
|
131
|
-
return self
|
|
132
|
-
|
|
133
|
-
def add_field(self, name: str, value: str, is_inline: bool = False):
|
|
134
|
-
"""Add a field to this embed.
|
|
135
|
-
|
|
136
|
-
Args:
|
|
137
|
-
name (str): field's title
|
|
138
|
-
value (str): field's text
|
|
139
|
-
is_inline (bool): if this field should be inlined
|
|
140
|
-
|
|
141
|
-
Returns:
|
|
142
|
-
(EmbedBuilder): self
|
|
143
|
-
"""
|
|
144
|
-
self.fields.append(_EmbedField(name=name, value=value, inline=is_inline))
|
|
145
|
-
return self
|
|
146
|
-
|
|
147
|
-
def set_timestamp(self):
|
|
148
|
-
"""Set this embed's timestamp.
|
|
149
|
-
|
|
150
|
-
Returns:
|
|
151
|
-
(EmbedBuilder): self
|
|
152
|
-
"""
|
|
153
|
-
self.timestamp = datetime.now(timezone.utc).isoformat()
|
|
154
|
-
return self
|