AdvancedTagscript 3.2.3__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.
- TagScriptEngine/__init__.py +227 -0
- TagScriptEngine/_warnings.py +88 -0
- TagScriptEngine/adapter/__init__.py +50 -0
- TagScriptEngine/adapter/discordadapters.py +596 -0
- TagScriptEngine/adapter/functionadapter.py +23 -0
- TagScriptEngine/adapter/intadapter.py +22 -0
- TagScriptEngine/adapter/objectadapter.py +35 -0
- TagScriptEngine/adapter/redbotadapters.py +161 -0
- TagScriptEngine/adapter/stringadapter.py +47 -0
- TagScriptEngine/block/__init__.py +130 -0
- TagScriptEngine/block/allowedmentions.py +60 -0
- TagScriptEngine/block/assign.py +43 -0
- TagScriptEngine/block/breakblock.py +41 -0
- TagScriptEngine/block/case.py +63 -0
- TagScriptEngine/block/command.py +141 -0
- TagScriptEngine/block/comment.py +29 -0
- TagScriptEngine/block/control.py +149 -0
- TagScriptEngine/block/cooldown.py +95 -0
- TagScriptEngine/block/count.py +68 -0
- TagScriptEngine/block/embedblock.py +306 -0
- TagScriptEngine/block/fiftyfifty.py +34 -0
- TagScriptEngine/block/helpers.py +164 -0
- TagScriptEngine/block/loosevariablegetter.py +40 -0
- TagScriptEngine/block/mathblock.py +164 -0
- TagScriptEngine/block/randomblock.py +51 -0
- TagScriptEngine/block/range.py +56 -0
- TagScriptEngine/block/redirect.py +42 -0
- TagScriptEngine/block/replaceblock.py +110 -0
- TagScriptEngine/block/require_blacklist.py +79 -0
- TagScriptEngine/block/shortcutredirect.py +23 -0
- TagScriptEngine/block/stopblock.py +38 -0
- TagScriptEngine/block/strf.py +70 -0
- TagScriptEngine/block/strictvariablegetter.py +38 -0
- TagScriptEngine/block/substr.py +25 -0
- TagScriptEngine/block/urlencodeblock.py +41 -0
- TagScriptEngine/exceptions.py +105 -0
- TagScriptEngine/interface/__init__.py +14 -0
- TagScriptEngine/interface/adapter.py +75 -0
- TagScriptEngine/interface/block.py +124 -0
- TagScriptEngine/interpreter.py +502 -0
- TagScriptEngine/py.typed +0 -0
- TagScriptEngine/utils.py +71 -0
- TagScriptEngine/verb.py +160 -0
- advancedtagscript-3.2.3.dist-info/METADATA +99 -0
- advancedtagscript-3.2.3.dist-info/RECORD +48 -0
- advancedtagscript-3.2.3.dist-info/WHEEL +5 -0
- advancedtagscript-3.2.3.dist-info/licenses/LICENSE +1 -0
- advancedtagscript-3.2.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import datetime
|
|
5
|
+
from random import choice
|
|
6
|
+
from typing import Any, Dict, Union, cast, Tuple
|
|
7
|
+
|
|
8
|
+
import discord
|
|
9
|
+
|
|
10
|
+
from ..verb import Verb
|
|
11
|
+
from ..utils import escape_content
|
|
12
|
+
from .._warnings import deprecated
|
|
13
|
+
from ..interface import Adapter, SimpleAdapter
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_log: logging.Logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
__all__: Tuple[str, ...] = (
|
|
20
|
+
"AttributeAdapter",
|
|
21
|
+
"DiscordAttributeAdapter",
|
|
22
|
+
"UserAdapter",
|
|
23
|
+
"MemberAdapter",
|
|
24
|
+
"DMChannelAdapter",
|
|
25
|
+
"ChannelAdapter",
|
|
26
|
+
"GuildAdapter",
|
|
27
|
+
"RoleAdapter",
|
|
28
|
+
"DiscordObjectAdapter",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AttributeAdapter(Adapter):
|
|
33
|
+
"""
|
|
34
|
+
.. deprecated:: 3.2.0
|
|
35
|
+
AttributeAdapter has been deprecated and will be removed in favor of
|
|
36
|
+
``TagScriptEngine.adapter.discordadpaters.DiscordAttributeAdapter`` or
|
|
37
|
+
consider using ``TagScriptEngine.interface.adapter.SimpleAdapter`` instead.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
__slots__: Tuple[str, ...] = ("object", "_attributes", "_methods")
|
|
41
|
+
|
|
42
|
+
@deprecated(
|
|
43
|
+
name="TagScriptEngine.adapter.discordadpaters.AttributeAdapter",
|
|
44
|
+
reason=(
|
|
45
|
+
"AttributeAdapter has been deprecated and will be removed in favor of "
|
|
46
|
+
"``TagScriptEngine.adapter.discordadpaters.DiscordAttributeAdapter`` or "
|
|
47
|
+
"consider using ``TagScriptEngine.interface.adapter.SimpleAdapter`` instead."
|
|
48
|
+
),
|
|
49
|
+
version="3.2.0",
|
|
50
|
+
)
|
|
51
|
+
def __init__(self, base: Union[discord.TextChannel, discord.Member, discord.Guild]) -> None:
|
|
52
|
+
self.object: Union[discord.TextChannel, discord.Member, discord.Guild] = base
|
|
53
|
+
created_at: datetime.datetime = getattr(
|
|
54
|
+
base, "created_at", None
|
|
55
|
+
) or discord.utils.snowflake_time(base.id)
|
|
56
|
+
self._attributes: Dict[str, Any] = {
|
|
57
|
+
"id": base.id,
|
|
58
|
+
"created_at": created_at,
|
|
59
|
+
"timestamp": int(created_at.timestamp()),
|
|
60
|
+
"name": getattr(base, "name", str(base)),
|
|
61
|
+
}
|
|
62
|
+
self._methods: Dict[str, Any] = {}
|
|
63
|
+
self.update_attributes()
|
|
64
|
+
self.update_methods()
|
|
65
|
+
|
|
66
|
+
def __repr__(self) -> str:
|
|
67
|
+
return f"<{type(self).__qualname__} object={self.object!r}>"
|
|
68
|
+
|
|
69
|
+
def update_attributes(self) -> None:
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
def update_methods(self) -> None:
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
def get_value(self, ctx: Verb) -> str:
|
|
76
|
+
should_escape = False
|
|
77
|
+
if ctx.parameter is None:
|
|
78
|
+
return_value = str(self.object)
|
|
79
|
+
else:
|
|
80
|
+
try:
|
|
81
|
+
value = self._attributes[ctx.parameter]
|
|
82
|
+
except KeyError:
|
|
83
|
+
if method := self._methods.get(ctx.parameter):
|
|
84
|
+
value = method()
|
|
85
|
+
else:
|
|
86
|
+
return # type: ignore
|
|
87
|
+
if isinstance(value, tuple):
|
|
88
|
+
value, should_escape = value
|
|
89
|
+
return_value: str = str(value) if value is not None else None # type: ignore
|
|
90
|
+
return escape_content(return_value) if should_escape else return_value
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class DiscordAttributeAdapter(
|
|
94
|
+
SimpleAdapter[
|
|
95
|
+
Union[
|
|
96
|
+
discord.TextChannel,
|
|
97
|
+
discord.DMChannel,
|
|
98
|
+
discord.User,
|
|
99
|
+
discord.Member,
|
|
100
|
+
discord.Guild,
|
|
101
|
+
discord.Role,
|
|
102
|
+
]
|
|
103
|
+
]
|
|
104
|
+
):
|
|
105
|
+
"""
|
|
106
|
+
.. versionadded:: 3.2.0
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
def __init__(
|
|
110
|
+
self,
|
|
111
|
+
base: Union[
|
|
112
|
+
discord.TextChannel,
|
|
113
|
+
discord.DMChannel,
|
|
114
|
+
discord.User,
|
|
115
|
+
discord.Member,
|
|
116
|
+
discord.Guild,
|
|
117
|
+
discord.Role,
|
|
118
|
+
],
|
|
119
|
+
) -> None:
|
|
120
|
+
super().__init__(base=base)
|
|
121
|
+
created_at: datetime.datetime = getattr(
|
|
122
|
+
base, "created_at", None
|
|
123
|
+
) or discord.utils.snowflake_time(base.id)
|
|
124
|
+
self._attributes.update(
|
|
125
|
+
{
|
|
126
|
+
"id": base.id,
|
|
127
|
+
"created_at": created_at,
|
|
128
|
+
"timestamp": int(created_at.timestamp()),
|
|
129
|
+
"name": getattr(base, "name", str(base)),
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
def __repr__(self) -> str:
|
|
134
|
+
return "<{} object={}>".format(type(self).__qualname__, self.object)
|
|
135
|
+
|
|
136
|
+
def get_value(self, ctx: Verb) -> str: # type: ignore
|
|
137
|
+
should_escape = False
|
|
138
|
+
if ctx.parameter is None:
|
|
139
|
+
return_value = str(self.object)
|
|
140
|
+
else:
|
|
141
|
+
try:
|
|
142
|
+
value = self._attributes[ctx.parameter]
|
|
143
|
+
except KeyError:
|
|
144
|
+
if method := self._methods.get(ctx.parameter):
|
|
145
|
+
value = method()
|
|
146
|
+
else:
|
|
147
|
+
_log.debug(
|
|
148
|
+
"No parameter named `{}` found for the `{}` Adapter.".format(
|
|
149
|
+
ctx.parameter, self.__class__.__name__
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
return # type: ignore
|
|
153
|
+
if isinstance(value, tuple):
|
|
154
|
+
value, should_escape = value
|
|
155
|
+
return_value = str(value) if value is not None else None
|
|
156
|
+
return escape_content(return_value) if should_escape else return_value # type: ignore
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class UserAdapter(DiscordAttributeAdapter):
|
|
160
|
+
"""
|
|
161
|
+
The ``{user}`` block with no parameters returns the user's full username,
|
|
162
|
+
but passing the attributes listed below to the block payload will return
|
|
163
|
+
that attribute instead.
|
|
164
|
+
|
|
165
|
+
**Usage:** ``{user([attribute])}``
|
|
166
|
+
|
|
167
|
+
**Payload:** None
|
|
168
|
+
|
|
169
|
+
**Parameter:** attribute, None
|
|
170
|
+
|
|
171
|
+
Attributes
|
|
172
|
+
----------
|
|
173
|
+
id
|
|
174
|
+
The user's Discord ID.
|
|
175
|
+
name
|
|
176
|
+
The user's username.
|
|
177
|
+
nick
|
|
178
|
+
The user's nickname, if they have one, else their username.
|
|
179
|
+
avatar
|
|
180
|
+
A link to the user's avatar, which can be used in embeds.
|
|
181
|
+
created_at
|
|
182
|
+
The user's account creation date.
|
|
183
|
+
timestamp
|
|
184
|
+
The user's account creation date as UTC timestamp.
|
|
185
|
+
mention
|
|
186
|
+
A formatted text that ping's the user.
|
|
187
|
+
bot
|
|
188
|
+
Wheather or not the user is a bot.
|
|
189
|
+
accent_color
|
|
190
|
+
The user's accent color if banner is not present.
|
|
191
|
+
avatar_decoration
|
|
192
|
+
A link to the user's avatar decoration.
|
|
193
|
+
|
|
194
|
+
.. versionadded:: 3.2.0
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
def update_attributes(self) -> None:
|
|
198
|
+
object: discord.User = cast(discord.User, self.object)
|
|
199
|
+
avatar_url: str = object.display_avatar.url
|
|
200
|
+
if asset := object.avatar_decoration:
|
|
201
|
+
decoration: Union[str, bool] = asset.with_format("png").url
|
|
202
|
+
else:
|
|
203
|
+
decoration: Union[str, bool] = False
|
|
204
|
+
additional_attributes: Dict[str, Any] = {
|
|
205
|
+
"nick": object.display_name,
|
|
206
|
+
"mention": object.mention,
|
|
207
|
+
"avatar": (avatar_url, False),
|
|
208
|
+
"bot": object.bot,
|
|
209
|
+
"accent_color": getattr(object, "accent_color", False),
|
|
210
|
+
"avatar_decoration": decoration,
|
|
211
|
+
}
|
|
212
|
+
self._attributes.update(additional_attributes)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class MemberAdapter(DiscordAttributeAdapter):
|
|
216
|
+
"""
|
|
217
|
+
The ``{author}`` block with no parameters returns the tag invoker's full username
|
|
218
|
+
and discriminator, but passing the attributes listed below to the block payload
|
|
219
|
+
will return that attribute instead.
|
|
220
|
+
|
|
221
|
+
**Aliases:** ``user``
|
|
222
|
+
|
|
223
|
+
**Usage:** ``{author([attribute])``
|
|
224
|
+
|
|
225
|
+
**Payload:** None
|
|
226
|
+
|
|
227
|
+
**Parameter:** attribute, None
|
|
228
|
+
|
|
229
|
+
Attributes
|
|
230
|
+
----------
|
|
231
|
+
id
|
|
232
|
+
The author's Discord ID.
|
|
233
|
+
name
|
|
234
|
+
The author's username.
|
|
235
|
+
nick
|
|
236
|
+
The author's nickname, if they have one, else their username.
|
|
237
|
+
avatar
|
|
238
|
+
A link to the author's avatar, which can be used in embeds.
|
|
239
|
+
discriminator
|
|
240
|
+
The author's discriminator.
|
|
241
|
+
created_at
|
|
242
|
+
The author's account creation date.
|
|
243
|
+
timestamp
|
|
244
|
+
The author's account creation date as a UTC timestamp.
|
|
245
|
+
joined_at
|
|
246
|
+
The date the author joined the server.
|
|
247
|
+
joinstamp
|
|
248
|
+
The author's join date as a UTC timestamp.
|
|
249
|
+
mention
|
|
250
|
+
A formatted text that pings the author.
|
|
251
|
+
bot
|
|
252
|
+
Whether or not the author is a bot.
|
|
253
|
+
color
|
|
254
|
+
The author's top role's color as a hex code.
|
|
255
|
+
top_role
|
|
256
|
+
The author's top role.
|
|
257
|
+
roleids
|
|
258
|
+
A list of the author's role IDs, split by spaces.
|
|
259
|
+
boost
|
|
260
|
+
If the user has boosted, this will be the UTC timestamp of when they did,
|
|
261
|
+
if not this will be empty.
|
|
262
|
+
timed_out
|
|
263
|
+
If the user is timed out, this will be the UTC timestamp of when they'll be untimed-out,
|
|
264
|
+
if not timed out this will be empty.
|
|
265
|
+
banner
|
|
266
|
+
The users banner url
|
|
267
|
+
"""
|
|
268
|
+
|
|
269
|
+
def update_attributes(self) -> None:
|
|
270
|
+
object: discord.Member = cast(discord.Member, self.object)
|
|
271
|
+
avatar_url: str = object.display_avatar.url
|
|
272
|
+
joined_at: datetime.datetime = getattr(object, "joined_at", self.object.created_at)
|
|
273
|
+
additional_attributes: Dict[str, Any] = {
|
|
274
|
+
"color": object.color,
|
|
275
|
+
"colour": object.color,
|
|
276
|
+
"nick": object.display_name,
|
|
277
|
+
"avatar": (avatar_url, False),
|
|
278
|
+
"discriminator": object.discriminator,
|
|
279
|
+
"joined_at": joined_at,
|
|
280
|
+
"joinstamp": int(joined_at.timestamp()),
|
|
281
|
+
"mention": object.mention,
|
|
282
|
+
"bot": object.bot,
|
|
283
|
+
"top_role": getattr(object, "top_role", ""),
|
|
284
|
+
"boost": getattr(object, "premium_since", ""),
|
|
285
|
+
"timed_out": getattr(object, "timed_out_until", ""),
|
|
286
|
+
"banner": object.banner.url if object.banner else "",
|
|
287
|
+
}
|
|
288
|
+
if roleids := getattr(self.object, "_roles", None):
|
|
289
|
+
additional_attributes["roleids"] = " ".join(str(r) for r in roleids)
|
|
290
|
+
self._attributes.update(additional_attributes)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class DMChannelAdapter(DiscordAttributeAdapter):
|
|
294
|
+
"""
|
|
295
|
+
The ``{channel}`` block with no parameters returns the channel's full name
|
|
296
|
+
but passing the attributes listed below to the block payload will return
|
|
297
|
+
the attribute instead.
|
|
298
|
+
|
|
299
|
+
**Usage:** ``{channel([attribute])``
|
|
300
|
+
|
|
301
|
+
**Payload:** None
|
|
302
|
+
|
|
303
|
+
**Parameter:** attribute, None
|
|
304
|
+
|
|
305
|
+
Attributes
|
|
306
|
+
----------
|
|
307
|
+
id
|
|
308
|
+
The channel's ID.
|
|
309
|
+
name
|
|
310
|
+
The channel's name.
|
|
311
|
+
created_at
|
|
312
|
+
The channel's creation date.
|
|
313
|
+
timestamp
|
|
314
|
+
The channel's creation date as a UTC timestamp.
|
|
315
|
+
jump_url
|
|
316
|
+
A link to the channel.
|
|
317
|
+
|
|
318
|
+
.. versionadded:: 3.2.0
|
|
319
|
+
"""
|
|
320
|
+
|
|
321
|
+
def update_attributes(self) -> None:
|
|
322
|
+
if isinstance(self.object, discord.DMChannel):
|
|
323
|
+
additional_attributes: Dict[str, Any] = {
|
|
324
|
+
"jump_url": getattr(self.object, "jump_url", None)
|
|
325
|
+
}
|
|
326
|
+
self._attributes.update(additional_attributes)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
class ChannelAdapter(DiscordAttributeAdapter):
|
|
330
|
+
"""
|
|
331
|
+
The ``{channel}`` block with no parameters returns the channel's full name
|
|
332
|
+
but passing the attributes listed below to the block payload
|
|
333
|
+
will return that attribute instead.
|
|
334
|
+
|
|
335
|
+
**Usage:** ``{channel([attribute])``
|
|
336
|
+
|
|
337
|
+
**Payload:** None
|
|
338
|
+
|
|
339
|
+
**Parameter:** attribute, None
|
|
340
|
+
|
|
341
|
+
Attributes
|
|
342
|
+
----------
|
|
343
|
+
id
|
|
344
|
+
The channel's ID.
|
|
345
|
+
name
|
|
346
|
+
The channel's name.
|
|
347
|
+
created_at
|
|
348
|
+
The channel's creation date.
|
|
349
|
+
timestamp
|
|
350
|
+
The channel's creation date as a UTC timestamp.
|
|
351
|
+
nsfw
|
|
352
|
+
Whether the channel is nsfw.
|
|
353
|
+
mention
|
|
354
|
+
A formatted text that pings the channel.
|
|
355
|
+
topic
|
|
356
|
+
The channel's topic.
|
|
357
|
+
category_id
|
|
358
|
+
The category the channel is associated with.
|
|
359
|
+
If no category channel, this will return empty.
|
|
360
|
+
jump_url
|
|
361
|
+
A link to the channel.
|
|
362
|
+
|
|
363
|
+
.. versionchanged:: 3.2.0
|
|
364
|
+
Added ``jump_url`` as a parameter.
|
|
365
|
+
"""
|
|
366
|
+
|
|
367
|
+
def update_attributes(self) -> None:
|
|
368
|
+
if isinstance(self.object, discord.TextChannel):
|
|
369
|
+
additional_attributes: Dict[str, Any] = {
|
|
370
|
+
"nsfw": self.object.nsfw,
|
|
371
|
+
"mention": self.object.mention,
|
|
372
|
+
"topic": self.object.topic or "",
|
|
373
|
+
"slowmode": self.object.slowmode_delay,
|
|
374
|
+
"category_id": self.object.category_id or "",
|
|
375
|
+
"jump_url": self.object.jump_url or None,
|
|
376
|
+
}
|
|
377
|
+
self._attributes.update(additional_attributes)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
class GuildAdapter(DiscordAttributeAdapter):
|
|
381
|
+
"""
|
|
382
|
+
The ``{server}`` block with no parameters returns the server's name
|
|
383
|
+
but passing the attributes listed below to the block payload
|
|
384
|
+
will return that attribute instead.
|
|
385
|
+
|
|
386
|
+
**Aliases:** ``guild``
|
|
387
|
+
|
|
388
|
+
**Usage:** ``{server([attribute])``
|
|
389
|
+
|
|
390
|
+
**Payload:** None
|
|
391
|
+
|
|
392
|
+
**Parameter:** attribute, None
|
|
393
|
+
|
|
394
|
+
Attributes
|
|
395
|
+
----------
|
|
396
|
+
id
|
|
397
|
+
The server's ID.
|
|
398
|
+
name
|
|
399
|
+
The server's name.
|
|
400
|
+
icon
|
|
401
|
+
A link to the server's icon, which can be used in embeds.
|
|
402
|
+
created_at
|
|
403
|
+
The server's creation date.
|
|
404
|
+
timestamp
|
|
405
|
+
The server's creation date as a UTC timestamp.
|
|
406
|
+
member_count
|
|
407
|
+
The server's member count.
|
|
408
|
+
bots
|
|
409
|
+
The number of bots in the server.
|
|
410
|
+
humans
|
|
411
|
+
The number of humans in the server.
|
|
412
|
+
description
|
|
413
|
+
The server's description if one is set, or "No description".
|
|
414
|
+
random
|
|
415
|
+
A random member from the server.
|
|
416
|
+
vanity
|
|
417
|
+
If guild has a vanity, this returns the vanity else empty.
|
|
418
|
+
owner_id
|
|
419
|
+
The server owner's id.
|
|
420
|
+
mfa
|
|
421
|
+
The server's mfa level.
|
|
422
|
+
boosters
|
|
423
|
+
The server's active booster count.
|
|
424
|
+
boost_level
|
|
425
|
+
The server's current boost level/tier.
|
|
426
|
+
discovery_splash
|
|
427
|
+
A link to the server's discovery splash.
|
|
428
|
+
invite_splash
|
|
429
|
+
A link to the server's invite splash.
|
|
430
|
+
banner
|
|
431
|
+
A link to the server's banner.
|
|
432
|
+
|
|
433
|
+
.. versionchanged:: 3.2.0
|
|
434
|
+
Added ``mfa``, ``boosters``, ``boost_level``,
|
|
435
|
+
``discovery_splash``, ``invite_splash`` & ``banner``.
|
|
436
|
+
"""
|
|
437
|
+
|
|
438
|
+
def update_attributes(self) -> None:
|
|
439
|
+
object: discord.Guild = cast(discord.Guild, self.object)
|
|
440
|
+
guild: discord.Guild = object
|
|
441
|
+
bots: int = 0
|
|
442
|
+
humans: int = 0
|
|
443
|
+
for m in guild.members:
|
|
444
|
+
if m.bot:
|
|
445
|
+
bots += 1
|
|
446
|
+
else:
|
|
447
|
+
humans += 1
|
|
448
|
+
member_count: int = getattr(guild, "member_count", 0)
|
|
449
|
+
icon_url: str = getattr(guild.icon, "url", "")
|
|
450
|
+
additional_attributes: Dict[str, Any] = {
|
|
451
|
+
"icon": (icon_url, False),
|
|
452
|
+
"member_count": member_count,
|
|
453
|
+
"members": member_count,
|
|
454
|
+
"bots": bots,
|
|
455
|
+
"humans": humans,
|
|
456
|
+
"description": guild.description or "No description.",
|
|
457
|
+
"vanity": guild.vanity_url_code or "No Vanity URL.",
|
|
458
|
+
"owner_id": guild.owner_id or "",
|
|
459
|
+
"mfa": guild.mfa_level,
|
|
460
|
+
"boosters": guild.premium_subscription_count,
|
|
461
|
+
"boost_level": guild.premium_tier,
|
|
462
|
+
"discovery_splash": getattr(guild.discovery_splash, "url", False),
|
|
463
|
+
"invite_splash": getattr(guild.splash, "url", False),
|
|
464
|
+
"banner": getattr(guild.banner, "url", False),
|
|
465
|
+
}
|
|
466
|
+
self._attributes.update(additional_attributes)
|
|
467
|
+
|
|
468
|
+
def update_methods(self) -> None:
|
|
469
|
+
additional_methods: Dict[str, Any] = {"random": self.random_member}
|
|
470
|
+
self._methods.update(additional_methods)
|
|
471
|
+
|
|
472
|
+
def random_member(self) -> discord.Member:
|
|
473
|
+
object: discord.Guild = cast(discord.Guild, self.object)
|
|
474
|
+
return choice(object.members)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
class RoleAdapter(DiscordAttributeAdapter):
|
|
478
|
+
"""
|
|
479
|
+
The ``{role}`` block with no parameters returns the role's full name
|
|
480
|
+
but passing the attributes listed below to the block payload will
|
|
481
|
+
return that attribute instead.
|
|
482
|
+
|
|
483
|
+
**Usage:** ``{role([attribute])}``
|
|
484
|
+
|
|
485
|
+
**Payload:** None
|
|
486
|
+
|
|
487
|
+
**Parameter:** attribute, None
|
|
488
|
+
|
|
489
|
+
Attributes
|
|
490
|
+
----------
|
|
491
|
+
id
|
|
492
|
+
The role's ID.
|
|
493
|
+
name
|
|
494
|
+
The role's name.
|
|
495
|
+
created_at
|
|
496
|
+
The role's creation date.
|
|
497
|
+
timestamp
|
|
498
|
+
The role's creation date as a UTC timestamp.
|
|
499
|
+
color
|
|
500
|
+
The role's color.
|
|
501
|
+
display_icon
|
|
502
|
+
The role's icon.
|
|
503
|
+
hoist
|
|
504
|
+
Wheather the role is hoisted or not.
|
|
505
|
+
managed
|
|
506
|
+
Wheather the role is managed or not.
|
|
507
|
+
mention
|
|
508
|
+
A formatted text that pings the role.
|
|
509
|
+
position
|
|
510
|
+
The role's position.
|
|
511
|
+
|
|
512
|
+
.. versionadded:: 3.2.0
|
|
513
|
+
"""
|
|
514
|
+
|
|
515
|
+
def update_attributes(self) -> None:
|
|
516
|
+
object: discord.Role = cast(discord.Role, self.object)
|
|
517
|
+
additional_attributes: Dict[str, Any] = {
|
|
518
|
+
"color": object.color,
|
|
519
|
+
"display_icon": getattr(object.display_icon, "url", False),
|
|
520
|
+
"hoist": object.hoist,
|
|
521
|
+
"managed": object.managed,
|
|
522
|
+
"mention": object.mention,
|
|
523
|
+
"position": object.position,
|
|
524
|
+
}
|
|
525
|
+
self._attributes.update(additional_attributes)
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
class DiscordObjectAdapter(Adapter):
|
|
529
|
+
"""
|
|
530
|
+
The ``{object}`` block with no parameters returs the discord object's ID,
|
|
531
|
+
but passing the attributes listed below to the block payload will return
|
|
532
|
+
that attribute instead.
|
|
533
|
+
|
|
534
|
+
**Usage:** ``{object([attribute])}``
|
|
535
|
+
|
|
536
|
+
**Payload:** None
|
|
537
|
+
|
|
538
|
+
**Parameter:** attribute, None
|
|
539
|
+
|
|
540
|
+
Attributes
|
|
541
|
+
----------
|
|
542
|
+
id
|
|
543
|
+
The object's Discord ID.
|
|
544
|
+
created_at
|
|
545
|
+
The object's creation date.
|
|
546
|
+
timestamp
|
|
547
|
+
The object's creation date as a UTC timestamp.
|
|
548
|
+
|
|
549
|
+
.. versionadded:: 3.2.0
|
|
550
|
+
"""
|
|
551
|
+
|
|
552
|
+
__slots__: Tuple[str, ...] = ("object", "_attributes", "_methods")
|
|
553
|
+
|
|
554
|
+
def __init__(self, base: discord.Object) -> None:
|
|
555
|
+
self.object: discord.Object = base
|
|
556
|
+
created_at: datetime.datetime = getattr(
|
|
557
|
+
base, "created_at", None
|
|
558
|
+
) or discord.utils.snowflake_time(base.id)
|
|
559
|
+
self._attributes: Dict[str, Any] = {
|
|
560
|
+
"id": base.id,
|
|
561
|
+
"created_at": created_at,
|
|
562
|
+
"timestamp": int(created_at.timestamp()),
|
|
563
|
+
}
|
|
564
|
+
self._methods: Dict[str, Any] = {}
|
|
565
|
+
self.update_attributes()
|
|
566
|
+
self.update_methods()
|
|
567
|
+
|
|
568
|
+
def __repr__(self) -> str:
|
|
569
|
+
return f"<{type(self).__qualname__} object={self.object!r}>"
|
|
570
|
+
|
|
571
|
+
def update_attributes(self) -> None:
|
|
572
|
+
pass
|
|
573
|
+
|
|
574
|
+
def update_methods(self) -> None:
|
|
575
|
+
pass
|
|
576
|
+
|
|
577
|
+
def get_value(self, ctx: Verb) -> str: # type: ignore
|
|
578
|
+
should_escape = False
|
|
579
|
+
|
|
580
|
+
if ctx.parameter is None:
|
|
581
|
+
return_value = str(self.object.id)
|
|
582
|
+
else:
|
|
583
|
+
try:
|
|
584
|
+
value = self._attributes[ctx.parameter]
|
|
585
|
+
except KeyError:
|
|
586
|
+
if method := self._methods.get(ctx.parameter):
|
|
587
|
+
value = method()
|
|
588
|
+
else:
|
|
589
|
+
return # type: ignore
|
|
590
|
+
|
|
591
|
+
if isinstance(value, tuple):
|
|
592
|
+
value, should_escape = value
|
|
593
|
+
|
|
594
|
+
return_value = str(value) if value is not None else None
|
|
595
|
+
|
|
596
|
+
return escape_content(return_value) if should_escape else return_value # type: ignore
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Callable, Tuple
|
|
4
|
+
|
|
5
|
+
from ..interface import Adapter
|
|
6
|
+
from ..verb import Verb
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
__all__: Tuple[str, ...] = ("FunctionAdapter",)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class FunctionAdapter(Adapter):
|
|
13
|
+
__slots__: Tuple[str, ...] = ("fn",)
|
|
14
|
+
|
|
15
|
+
def __init__(self, function_pointer: Callable[[], str]) -> None:
|
|
16
|
+
self.fn = function_pointer
|
|
17
|
+
super().__init__()
|
|
18
|
+
|
|
19
|
+
def __repr__(self) -> str:
|
|
20
|
+
return f"<{type(self).__qualname__} fn={self.fn!r}>"
|
|
21
|
+
|
|
22
|
+
def get_value(self, ctx: Verb) -> str: # type: ignore
|
|
23
|
+
return str(self.fn())
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Tuple
|
|
4
|
+
|
|
5
|
+
from ..interface import Adapter
|
|
6
|
+
from ..verb import Verb
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
__all__: Tuple[str, ...] = ("IntAdapter",)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class IntAdapter(Adapter):
|
|
13
|
+
__slots__: Tuple[str, ...] = ("integer",)
|
|
14
|
+
|
|
15
|
+
def __init__(self, integer: int) -> None:
|
|
16
|
+
self.integer: int = int(integer)
|
|
17
|
+
|
|
18
|
+
def __repr__(self) -> str:
|
|
19
|
+
return f"<{type(self).__qualname__} integer={repr(self.integer)}>"
|
|
20
|
+
|
|
21
|
+
def get_value(self, ctx: Verb) -> str: # type: ignore
|
|
22
|
+
return str(self.integer)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Tuple
|
|
4
|
+
from inspect import ismethod
|
|
5
|
+
|
|
6
|
+
from ..interface import Adapter
|
|
7
|
+
from ..verb import Verb
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
__all__: Tuple[str, ...] = ("SafeObjectAdapter",)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SafeObjectAdapter(Adapter):
|
|
14
|
+
__slots__: Tuple[str, ...] = ("object",)
|
|
15
|
+
|
|
16
|
+
def __init__(self, base) -> None:
|
|
17
|
+
self.object = base
|
|
18
|
+
|
|
19
|
+
def __repr__(self) -> str:
|
|
20
|
+
return f"<{type(self).__qualname__} object={repr(self.object)}>"
|
|
21
|
+
|
|
22
|
+
def get_value(self, ctx: Verb) -> str:
|
|
23
|
+
if ctx.parameter is None:
|
|
24
|
+
return str(self.object)
|
|
25
|
+
if ctx.parameter.startswith("_") or "." in ctx.parameter:
|
|
26
|
+
return # type: ignore
|
|
27
|
+
try:
|
|
28
|
+
attribute = getattr(self.object, ctx.parameter)
|
|
29
|
+
except AttributeError:
|
|
30
|
+
return # type: ignore
|
|
31
|
+
if ismethod(attribute):
|
|
32
|
+
return # type: ignore
|
|
33
|
+
if isinstance(attribute, float):
|
|
34
|
+
attribute = int(attribute)
|
|
35
|
+
return str(attribute)
|