dshellInterpreter 0.2.13__py3-none-any.whl → 0.2.13.2__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 dshellInterpreter might be problematic. Click here for more details.
- Dshell/DISCORD_COMMANDS/dshell_message.py +11 -7
- Dshell/_DshellInterpreteur/dshell_interpreter.py +60 -0
- Dshell/_DshellParser/ast_nodes.py +83 -1
- Dshell/_DshellParser/dshell_parser.py +30 -0
- Dshell/_DshellTokenizer/dshell_keywords.py +1 -1
- {dshellinterpreter-0.2.13.dist-info → dshellinterpreter-0.2.13.2.dist-info}/METADATA +2 -1
- {dshellinterpreter-0.2.13.dist-info → dshellinterpreter-0.2.13.2.dist-info}/RECORD +10 -10
- {dshellinterpreter-0.2.13.dist-info → dshellinterpreter-0.2.13.2.dist-info}/WHEEL +0 -0
- {dshellinterpreter-0.2.13.dist-info → dshellinterpreter-0.2.13.2.dist-info}/licenses/LICENSE +0 -0
- {dshellinterpreter-0.2.13.dist-info → dshellinterpreter-0.2.13.2.dist-info}/top_level.txt +0 -0
|
@@ -4,7 +4,10 @@ from discord import Embed, Message
|
|
|
4
4
|
from discord.ext import commands
|
|
5
5
|
from discord.abc import Messageable
|
|
6
6
|
|
|
7
|
+
from pycordViews import EasyModifiedViews
|
|
8
|
+
|
|
7
9
|
from .utils.utils_message import utils_get_message
|
|
10
|
+
from .._utils import NoneType
|
|
8
11
|
|
|
9
12
|
__all__ = [
|
|
10
13
|
'dshell_send_message',
|
|
@@ -21,7 +24,7 @@ __all__ = [
|
|
|
21
24
|
]
|
|
22
25
|
|
|
23
26
|
|
|
24
|
-
async def dshell_send_message(ctx: Message, message=None, delete=None, channel=None, embeds=None):
|
|
27
|
+
async def dshell_send_message(ctx: Message, message=None, delete=None, channel=None, embeds=None, view=None) -> int:
|
|
25
28
|
"""
|
|
26
29
|
Sends a message on Discord
|
|
27
30
|
"""
|
|
@@ -36,18 +39,19 @@ async def dshell_send_message(ctx: Message, message=None, delete=None, channel=N
|
|
|
36
39
|
|
|
37
40
|
from .._DshellParser.ast_nodes import ListNode
|
|
38
41
|
|
|
39
|
-
if embeds
|
|
40
|
-
|
|
42
|
+
if not isinstance(embeds, (ListNode, Embed, NoneType)):
|
|
43
|
+
raise Exception(f'Embeds must be a list of Embed objects or a single Embed object, not {type(embeds)} !')
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
if isinstance(embeds, Embed):
|
|
43
46
|
embeds = ListNode([embeds])
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
raise Exception(f'
|
|
48
|
+
if not isinstance(channel_to_send, (EasyModifiedViews, NoneType)):
|
|
49
|
+
raise Exception(f'Channel must be an UI or None, not {type(channel_to_send)} !')
|
|
47
50
|
|
|
48
51
|
sended_message = await channel_to_send.send(message,
|
|
49
52
|
delete_after=delete,
|
|
50
|
-
embeds=embeds
|
|
53
|
+
embeds=embeds,
|
|
54
|
+
view=view)
|
|
51
55
|
|
|
52
56
|
return sended_message.id
|
|
53
57
|
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
from asyncio import sleep
|
|
2
2
|
from re import findall
|
|
3
3
|
from typing import TypeVar, Union, Any, Optional, Callable
|
|
4
|
+
from random import choice
|
|
5
|
+
from string import ascii_letters, digits
|
|
4
6
|
from copy import deepcopy
|
|
7
|
+
from pycordViews import SelectMenu, EasyModifiedViews
|
|
5
8
|
|
|
6
9
|
from discord import AutoShardedBot, Embed, Colour, PermissionOverwrite, Permissions, Guild, Member, Role, Message
|
|
10
|
+
from discord.ui import Button
|
|
7
11
|
from discord.abc import PrivateChannel
|
|
8
12
|
|
|
9
13
|
from .._DshellParser.ast_nodes import *
|
|
@@ -120,6 +124,9 @@ class DshellInterpreteur:
|
|
|
120
124
|
elif isinstance(first_node, PermissionNode):
|
|
121
125
|
self.env[node.name.value] = build_permission(first_node.body, self)
|
|
122
126
|
|
|
127
|
+
elif isinstance(first_node, UiNode):
|
|
128
|
+
self.env[node.name.value] = build_ui(first_node, self)
|
|
129
|
+
|
|
123
130
|
else:
|
|
124
131
|
self.env[node.name.value] = eval_expression(node.body, self)
|
|
125
132
|
|
|
@@ -401,6 +408,59 @@ def build_colour(color: Union[int, ListNode]) -> Union[Colour, int]:
|
|
|
401
408
|
raise TypeError(f"Color must be an integer or a ListNode, not {type(color)} !")
|
|
402
409
|
|
|
403
410
|
|
|
411
|
+
def build_ui(ui_node: UiNode, interpreter: DshellInterpreteur) -> EasyModifiedViews:
|
|
412
|
+
"""
|
|
413
|
+
Builds a UI component from the UiNode.
|
|
414
|
+
Can accept buttons and select menus.
|
|
415
|
+
:param ui_node:
|
|
416
|
+
:param interpreter:
|
|
417
|
+
:return:
|
|
418
|
+
"""
|
|
419
|
+
view = EasyModifiedViews()
|
|
420
|
+
|
|
421
|
+
for component in ui_node.buttons:
|
|
422
|
+
b = Button
|
|
423
|
+
args_button: dict[str, list[Any]] = regroupe_commandes(component.body, interpreter)[0]
|
|
424
|
+
args_button.pop('--*', ())
|
|
425
|
+
code = args_button.pop('code', None)
|
|
426
|
+
args = args_button.pop('*', ())
|
|
427
|
+
b(*args, **args_button)
|
|
428
|
+
|
|
429
|
+
custom_id = ''.join(choice(ascii_letters + digits) for _ in range(20))
|
|
430
|
+
b.custom_id = custom_id
|
|
431
|
+
|
|
432
|
+
view.add_items(b)
|
|
433
|
+
view.set_callable(custom_id, _callable=ui_button_callback, data={'code': code})
|
|
434
|
+
|
|
435
|
+
return view
|
|
436
|
+
|
|
437
|
+
async def ui_button_callback(button, interaction, data):
|
|
438
|
+
code = data.pop('code', None)
|
|
439
|
+
local_env = {}
|
|
440
|
+
if code is not None:
|
|
441
|
+
local_env = {
|
|
442
|
+
'__ret__': None,
|
|
443
|
+
'__guild__': interaction.guild.name if interaction.guild else None,
|
|
444
|
+
'__channel__': interaction.channel.name if interaction.channel else None,
|
|
445
|
+
'__author__': interaction.user.name,
|
|
446
|
+
'__author_display_name__': interaction.user.display_name,
|
|
447
|
+
'__author_avatar__': interaction.user.display_avatar.url if interaction.user.display_avatar else None,
|
|
448
|
+
'__author_discriminator__': interaction.user.discriminator,
|
|
449
|
+
'__author_bot__': interaction.user.bot,
|
|
450
|
+
'__author_nick__': interaction.user.nick if hasattr(interaction.user, 'nick') else None,
|
|
451
|
+
'__author_id__': interaction.user.id,
|
|
452
|
+
'__message__': interaction.message.content if hasattr(interaction.message, 'content') else None,
|
|
453
|
+
'__message_id__': interaction.message.id if hasattr(interaction.message, 'id') else None,
|
|
454
|
+
'__channel_name__': interaction.channel.name if interaction.channel else None,
|
|
455
|
+
'__channel_type__': interaction.channel.type.name if hasattr(interaction.channel, 'type') else None,
|
|
456
|
+
'__channel_id__': interaction.channel.id if interaction.channel else None,
|
|
457
|
+
'__private_channel__': isinstance(interaction.channel, PrivateChannel),
|
|
458
|
+
}
|
|
459
|
+
local_env.update(data)
|
|
460
|
+
x = DshellInterpreteur(code, interaction, debug=False)
|
|
461
|
+
x.env.update(local_env)
|
|
462
|
+
await x.execute()
|
|
463
|
+
|
|
404
464
|
def build_permission(body: list[Token], interpreter: DshellInterpreteur) -> dict[
|
|
405
465
|
Union[Member, Role], PermissionOverwrite]:
|
|
406
466
|
"""
|
|
@@ -20,7 +20,10 @@ __all__ = [
|
|
|
20
20
|
'IdentOperationNode',
|
|
21
21
|
'ListNode',
|
|
22
22
|
'PermissionNode',
|
|
23
|
-
'ParamNode'
|
|
23
|
+
'ParamNode',
|
|
24
|
+
'UiNode',
|
|
25
|
+
'UiButtonNode',
|
|
26
|
+
'UiSelectNode'
|
|
24
27
|
]
|
|
25
28
|
|
|
26
29
|
|
|
@@ -439,6 +442,85 @@ class ParamNode(ASTNode):
|
|
|
439
442
|
}
|
|
440
443
|
|
|
441
444
|
|
|
445
|
+
class UiButtonNode(ASTNode):
|
|
446
|
+
"""
|
|
447
|
+
Node representing a UI button component in the AST.
|
|
448
|
+
This is used to define button elements for commands in Dshell.
|
|
449
|
+
"""
|
|
450
|
+
|
|
451
|
+
def __init__(self, body: list[Token]):
|
|
452
|
+
"""
|
|
453
|
+
:param body: list of tokens representing the button component
|
|
454
|
+
"""
|
|
455
|
+
self.body = body
|
|
456
|
+
|
|
457
|
+
def __repr__(self):
|
|
458
|
+
return f"<UI BUTTON> - {self.body}"
|
|
459
|
+
|
|
460
|
+
def to_dict(self):
|
|
461
|
+
"""
|
|
462
|
+
Convert the UiButtonNode to a dictionary representation.
|
|
463
|
+
:return: Dictionary representation of the UiButtonNode.
|
|
464
|
+
"""
|
|
465
|
+
return {
|
|
466
|
+
"type": "UiButtonNode",
|
|
467
|
+
"body": [token.to_dict() for token in self.body]
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
class UiSelectNode(ASTNode):
|
|
471
|
+
"""
|
|
472
|
+
Node representing a UI select component in the AST.
|
|
473
|
+
This is used to define select elements for commands in Dshell.
|
|
474
|
+
"""
|
|
475
|
+
|
|
476
|
+
def __init__(self, body: list[Token]):
|
|
477
|
+
"""
|
|
478
|
+
:param body: list of tokens representing the select component
|
|
479
|
+
"""
|
|
480
|
+
self.body = body
|
|
481
|
+
|
|
482
|
+
def __repr__(self):
|
|
483
|
+
return f"<UI SELECT> - {self.body}"
|
|
484
|
+
|
|
485
|
+
def to_dict(self):
|
|
486
|
+
"""
|
|
487
|
+
Convert the UiSelectNode to a dictionary representation.
|
|
488
|
+
:return: Dictionary representation of the UiSelectNode.
|
|
489
|
+
"""
|
|
490
|
+
return {
|
|
491
|
+
"type": "UiSelectNode",
|
|
492
|
+
"body": [token.to_dict() for token in self.body]
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
class UiNode(ASTNode):
|
|
496
|
+
"""
|
|
497
|
+
Node representing a UI component in the AST.
|
|
498
|
+
This is used to define UI elements for commands in Dshell.
|
|
499
|
+
"""
|
|
500
|
+
|
|
501
|
+
def __init__(self, body, buttons: Optional[list[UiButtonNode]] = None,
|
|
502
|
+
selects: Optional[list[UiSelectNode]] = None):
|
|
503
|
+
"""
|
|
504
|
+
:param body: list of tokens representing the UI component
|
|
505
|
+
"""
|
|
506
|
+
self.body = body
|
|
507
|
+
self.buttons = buttons or []
|
|
508
|
+
self.selects = selects or []
|
|
509
|
+
|
|
510
|
+
def __repr__(self):
|
|
511
|
+
return f"<UI> - {self.buttons}\n\n - {self.selects}"
|
|
512
|
+
|
|
513
|
+
def to_dict(self):
|
|
514
|
+
"""
|
|
515
|
+
Convert the UiNode to a dictionary representation.
|
|
516
|
+
:return: Dictionary representation of the UiNode.
|
|
517
|
+
"""
|
|
518
|
+
return {
|
|
519
|
+
"type": "UiNode",
|
|
520
|
+
"buttons": [token.to_dict() for token in self.buttons],
|
|
521
|
+
"selects": [token.to_dict() for token in self.selects],
|
|
522
|
+
}
|
|
523
|
+
|
|
442
524
|
class ListNode(ASTNode):
|
|
443
525
|
"""
|
|
444
526
|
Node representing a list structure in the AST.
|
|
@@ -24,6 +24,9 @@ from .ast_nodes import (ASTNode,
|
|
|
24
24
|
FieldEmbedNode,
|
|
25
25
|
PermissionNode,
|
|
26
26
|
ParamNode,
|
|
27
|
+
UiNode,
|
|
28
|
+
UiButtonNode,
|
|
29
|
+
UiSelectNode,
|
|
27
30
|
StartNode)
|
|
28
31
|
from .._DshellTokenizer import dshell_operators
|
|
29
32
|
from .._DshellTokenizer.dshell_token_type import DshellTokenType as DTT
|
|
@@ -185,6 +188,33 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
185
188
|
blocks.pop()
|
|
186
189
|
return blocks, pointeur
|
|
187
190
|
|
|
191
|
+
elif first_token_line.value == 'ui':
|
|
192
|
+
ui_node = UiNode([])
|
|
193
|
+
var_node = VarNode(tokens_by_line[1], body=[ui_node])
|
|
194
|
+
last_block.body.append(var_node)
|
|
195
|
+
_, p = parse(token_lines[pointeur + 1:], ui_node)
|
|
196
|
+
pointeur += p + 1
|
|
197
|
+
|
|
198
|
+
elif first_token_line.value == '#ui':
|
|
199
|
+
if not isinstance(last_block, UiNode):
|
|
200
|
+
raise SyntaxError(f'[#UI] No UI open on line {first_token_line.position} !')
|
|
201
|
+
blocks.pop()
|
|
202
|
+
return blocks, pointeur
|
|
203
|
+
|
|
204
|
+
elif first_token_line.value == 'button':
|
|
205
|
+
if not isinstance(last_block, UiNode):
|
|
206
|
+
raise SyntaxError(f'[BUTTON] No UI open on line {first_token_line.position} !')
|
|
207
|
+
button_node = UiButtonNode(tokens_by_line[1:])
|
|
208
|
+
last_block.body.append(button_node)
|
|
209
|
+
pointeur += 1
|
|
210
|
+
|
|
211
|
+
elif first_token_line.value == 'select':
|
|
212
|
+
if not isinstance(last_block, UiNode):
|
|
213
|
+
raise SyntaxError(f'[SELECT] No UI open on line {first_token_line.position} !')
|
|
214
|
+
select_node = UiSelectNode(tokens_by_line[1:])
|
|
215
|
+
last_block.body.append(select_node)
|
|
216
|
+
pointeur += 1
|
|
217
|
+
|
|
188
218
|
############################## AUTRE ##############################
|
|
189
219
|
|
|
190
220
|
elif first_token_line.type == DTT.IDENT:
|
|
@@ -21,7 +21,7 @@ dshell_keyword: set[str] = {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
dshell_discord_keyword: set[str] = {
|
|
24
|
-
'embed', '#embed', 'field', 'perm', 'permission', '#perm', '#permission'
|
|
24
|
+
'embed', '#embed', 'field', 'perm', 'permission', '#perm', '#permission', 'ui', '#ui', 'button', 'select'
|
|
25
25
|
}
|
|
26
26
|
dshell_commands: dict[str, Callable] = {
|
|
27
27
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dshellInterpreter
|
|
3
|
-
Version: 0.2.13
|
|
3
|
+
Version: 0.2.13.2
|
|
4
4
|
Summary: A Discord bot interpreter for creating custom commands and automations.
|
|
5
5
|
Home-page: https://github.com/BOXERRMD/Dshell_Interpreter
|
|
6
6
|
Author: Chronos
|
|
@@ -17,6 +17,7 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: py-cord==2.6.1
|
|
19
19
|
Requires-Dist: requests
|
|
20
|
+
Requires-Dist: pycordviews
|
|
20
21
|
Dynamic: author
|
|
21
22
|
Dynamic: author-email
|
|
22
23
|
Dynamic: classifier
|
|
@@ -3,23 +3,23 @@ Dshell/_utils.py,sha256=PJ3fwn8IMqUMnW9oTwfr9v4--rzHIhhLQoVVqjwjoJU,23
|
|
|
3
3
|
Dshell/DISCORD_COMMANDS/__init__.py,sha256=8JPQ-6-s8PkaacmOfQgyczUiLM6rUSceHEJ60oNSis0,173
|
|
4
4
|
Dshell/DISCORD_COMMANDS/dshell_channel.py,sha256=qpNe3oE5VyLCmOeCjWlt0rvaSBv2yrkmJgrRswrNOZM,15721
|
|
5
5
|
Dshell/DISCORD_COMMANDS/dshell_member.py,sha256=5Iw-2dydhYMZOw2nx0svZP9JpZWHOXC0qkL9tClJHtw,8840
|
|
6
|
-
Dshell/DISCORD_COMMANDS/dshell_message.py,sha256=
|
|
6
|
+
Dshell/DISCORD_COMMANDS/dshell_message.py,sha256=WVOXoXmgKS_YEGNptwzC8370hoJGOBzJSx7lwD_6s5k,7271
|
|
7
7
|
Dshell/DISCORD_COMMANDS/dshell_pastbin.py,sha256=TkWFGRRTvhhJgvwkDFx9Fz4UM2UUFwxyq0laMVx0mUk,881
|
|
8
8
|
Dshell/DISCORD_COMMANDS/dshell_role.py,sha256=t_yRZRD0FKE2gT4dIDIsHz2PSZZztDVEkkqkG_OkNh4,5002
|
|
9
9
|
Dshell/DISCORD_COMMANDS/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
Dshell/DISCORD_COMMANDS/utils/utils_message.py,sha256=Pn0ljyeCvRfY4tlWHrSbIsxSFZZ5J4lDaeVme3WHp9o,1239
|
|
11
11
|
Dshell/DISCORD_COMMANDS/utils/utils_thread.py,sha256=tVl4msEwrWHY-0AytI6eY3JSs-eIFUigDSJfK9mT1ww,1457
|
|
12
12
|
Dshell/_DshellInterpreteur/__init__.py,sha256=xy5-J-R3YmY99JF3NBHTRRLsComFxpjnCA5xacISctU,35
|
|
13
|
-
Dshell/_DshellInterpreteur/dshell_interpreter.py,sha256=
|
|
13
|
+
Dshell/_DshellInterpreteur/dshell_interpreter.py,sha256=rHRCoLvT6J1mtyYm9jGH5XlbRAjU7pawAVxRv6a4B9k,25956
|
|
14
14
|
Dshell/_DshellParser/__init__.py,sha256=ONDfhZMvClqP_6tE8SLjp-cf3pXL-auQYnfYRrHZxC4,56
|
|
15
|
-
Dshell/_DshellParser/ast_nodes.py,sha256=
|
|
16
|
-
Dshell/_DshellParser/dshell_parser.py,sha256=
|
|
15
|
+
Dshell/_DshellParser/ast_nodes.py,sha256=uKSbK32Ez2wRX9lnH4DA-Ne3yq2v73YJ-_6ObA8U14k,17749
|
|
16
|
+
Dshell/_DshellParser/dshell_parser.py,sha256=hWatNRY6E3F6u-Y71dM45wnIeMLoInJh1vlXAD44rJ0,16969
|
|
17
17
|
Dshell/_DshellTokenizer/__init__.py,sha256=LIQSRhDx2B9pmPx5ADMwwD0Xr9ybneVLhHH8qrJWw_s,172
|
|
18
|
-
Dshell/_DshellTokenizer/dshell_keywords.py,sha256=
|
|
18
|
+
Dshell/_DshellTokenizer/dshell_keywords.py,sha256=HtrOQiND_TdM2pdNNAdjBZK2Lhzm2_9umY2dmKfFMTQ,5675
|
|
19
19
|
Dshell/_DshellTokenizer/dshell_token_type.py,sha256=gYIb2XN2YcgeRgmar_rBDS5CGmwfmxihu8mOW_d6lbE,1533
|
|
20
20
|
Dshell/_DshellTokenizer/dshell_tokenizer.py,sha256=LZGs4Ytuyx9Galazqtz32lS4Mmu9yZya1B7AzFQAQOk,7150
|
|
21
|
-
dshellinterpreter-0.2.13.dist-info/licenses/LICENSE,sha256=lNgcw1_xb7QENAQi3uHGymaFtbs0RV-ihiCd7AoLQjA,1082
|
|
22
|
-
dshellinterpreter-0.2.13.dist-info/METADATA,sha256=
|
|
23
|
-
dshellinterpreter-0.2.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
-
dshellinterpreter-0.2.13.dist-info/top_level.txt,sha256=B4CMhtmchGwPQJLuqUy0GhRG-0cUGxKL4GqEbCiB_vE,7
|
|
25
|
-
dshellinterpreter-0.2.13.dist-info/RECORD,,
|
|
21
|
+
dshellinterpreter-0.2.13.2.dist-info/licenses/LICENSE,sha256=lNgcw1_xb7QENAQi3uHGymaFtbs0RV-ihiCd7AoLQjA,1082
|
|
22
|
+
dshellinterpreter-0.2.13.2.dist-info/METADATA,sha256=aCTDttVPGUrUJ0g5UBbp7SSi9p0Hka22qV1_wGAcOxU,1151
|
|
23
|
+
dshellinterpreter-0.2.13.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
dshellinterpreter-0.2.13.2.dist-info/top_level.txt,sha256=B4CMhtmchGwPQJLuqUy0GhRG-0cUGxKL4GqEbCiB_vE,7
|
|
25
|
+
dshellinterpreter-0.2.13.2.dist-info/RECORD,,
|
|
File without changes
|
{dshellinterpreter-0.2.13.dist-info → dshellinterpreter-0.2.13.2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|