dshellInterpreter 1.1.4.2__tar.gz → 1.1.4.4__tar.gz
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.
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/__init__.py +1 -0
- dshellinterpreter-1.1.4.4/Dshell/DISCORD_COMMANDS/dshell_file.py +68 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_message.py +41 -8
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_type_validation.py +30 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellParser/ast_nodes.py +113 -2
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellParser/dshell_parser.py +24 -15
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellTokenizer/dshell_keywords.py +8 -2
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellTokenizer/dshell_tokenizer.py +4 -3
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/full_import.py +1 -3
- {dshellinterpreter-1.1.4.2/dshellInterpreter.egg-info → dshellinterpreter-1.1.4.4}/PKG-INFO +1 -1
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4/dshellInterpreter.egg-info}/PKG-INFO +1 -1
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/dshellInterpreter.egg-info/SOURCES.txt +1 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/setup.py +1 -1
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_channel.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_embed.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_interaction.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_member.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_role.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_ui.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/__init__.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_global.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_list.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_member.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_message.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_numbers.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_permissions.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_string.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_thread.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/__init__.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/cached_messages.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/dshell_arguments.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/dshell_interpreter.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/dshell_scope.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/errors.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/utils_interpreter.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellParser/__init__.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellPreProcess/__init__.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellPreProcess/dshell_preprocess.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellTokenizer/__init__.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellTokenizer/dshell_token_type.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/__init__.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/regex_test.py +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/LICENSE +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/README.md +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/dshellInterpreter.egg-info/dependency_links.txt +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/dshellInterpreter.egg-info/requires.txt +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/dshellInterpreter.egg-info/top_level.txt +0 -0
- {dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/setup.cfg +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from ..full_import import Message, Union, PartialMessage, Optional
|
|
2
|
+
from ..DshellParser.ast_nodes import ListNode, AttachmentNode, FileNode
|
|
3
|
+
|
|
4
|
+
from .utils.utils_message import utils_get_message
|
|
5
|
+
from .utils.utils_type_validation import (_validate_required_file_node,
|
|
6
|
+
_validate_required_string,
|
|
7
|
+
_validate_optional_string,
|
|
8
|
+
_validate_required_bool)
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
async def dshell_get_message_files(ctx: Message, message: Union[str, int]) -> ListNode:
|
|
15
|
+
"""
|
|
16
|
+
Récupère les fichiers d'un message
|
|
17
|
+
:param ctx:
|
|
18
|
+
:param message:
|
|
19
|
+
:return:
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
target_message = ctx if message is None else utils_get_message(ctx, message)
|
|
23
|
+
|
|
24
|
+
attachments_list: ListNode = ListNode([], 0)
|
|
25
|
+
|
|
26
|
+
if isinstance(target_message, PartialMessage):
|
|
27
|
+
target_message = await target_message.fetch()
|
|
28
|
+
|
|
29
|
+
for attachment in target_message.attachments:
|
|
30
|
+
attachments_list.add(AttachmentNode(attachment))
|
|
31
|
+
|
|
32
|
+
return attachments_list
|
|
33
|
+
|
|
34
|
+
async def dshell_read_file(ctx: Message, file: AttachmentNode) -> str:
|
|
35
|
+
"""
|
|
36
|
+
Lit en entier un fichier
|
|
37
|
+
:param ctx:
|
|
38
|
+
:param file:
|
|
39
|
+
:return:
|
|
40
|
+
"""
|
|
41
|
+
_CMD = "rf"
|
|
42
|
+
_validate_required_file_node(file, 'file', _CMD)
|
|
43
|
+
|
|
44
|
+
return await file.read()
|
|
45
|
+
|
|
46
|
+
async def dshell_write_file(ctx: Message,
|
|
47
|
+
file: Optional[FileNode] = None,
|
|
48
|
+
message: str = "",
|
|
49
|
+
append: bool = False,
|
|
50
|
+
filename: Optional[str] = None) -> FileNode:
|
|
51
|
+
"""
|
|
52
|
+
Ecrit dans un fichier
|
|
53
|
+
:param ctx:
|
|
54
|
+
:param file:
|
|
55
|
+
:param message:
|
|
56
|
+
:param append:
|
|
57
|
+
:param filename:
|
|
58
|
+
:return:
|
|
59
|
+
"""
|
|
60
|
+
_validate_required_string(message, 'message', 'wf')
|
|
61
|
+
_validate_required_bool(append, 'append', 'wf')
|
|
62
|
+
_validate_optional_string(filename, 'filename', 'wf')
|
|
63
|
+
|
|
64
|
+
target_file = file if isinstance(file, FileNode) else FileNode(filename)
|
|
65
|
+
|
|
66
|
+
target_file.write(bytearray(message, "utf-8"), append)
|
|
67
|
+
|
|
68
|
+
return target_file
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_message.py
RENAMED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from Dshell.full_import import (Message,
|
|
2
2
|
Embed,
|
|
3
|
-
PartialMessage
|
|
3
|
+
PartialMessage,
|
|
4
|
+
File)
|
|
4
5
|
|
|
5
|
-
from ..DshellParser.ast_nodes import ListNode,
|
|
6
|
+
from ..DshellParser.ast_nodes import ListNode, FileNode
|
|
6
7
|
|
|
7
8
|
from .utils.utils_message import utils_get_message, utils_autorised_mentions
|
|
8
9
|
from .utils.utils_type_validation import (_validate_optional_number,
|
|
@@ -14,7 +15,9 @@ from .utils.utils_type_validation import (_validate_optional_number,
|
|
|
14
15
|
_validate_required_bool,
|
|
15
16
|
_validate_required_int,
|
|
16
17
|
_validate_not_none,
|
|
17
|
-
_validate_optional_eval_group_node
|
|
18
|
+
_validate_optional_eval_group_node,
|
|
19
|
+
_validate_optional_list_node,
|
|
20
|
+
_validate_required_file_node)
|
|
18
21
|
from ..DshellInterpreteur.cached_messages import dshell_cached_messages
|
|
19
22
|
|
|
20
23
|
from Dshell.full_import import Optional, Union, compile, DOTALL
|
|
@@ -55,6 +58,7 @@ async def dshell_send_message(ctx: Message,
|
|
|
55
58
|
users_mentions: bool = True,
|
|
56
59
|
reply_mention: bool = False,
|
|
57
60
|
embeds=None,
|
|
61
|
+
files: Optional[ListNode] = None,
|
|
58
62
|
view=None) -> int:
|
|
59
63
|
"""
|
|
60
64
|
Sends a message on Discord
|
|
@@ -67,6 +71,7 @@ async def dshell_send_message(ctx: Message,
|
|
|
67
71
|
_validate_required_bool(roles_mentions, "Roles mentions", _CMD)
|
|
68
72
|
_validate_required_bool(users_mentions, "Users mentions", _CMD)
|
|
69
73
|
_validate_required_bool(reply_mention, "Reply mention", _CMD)
|
|
74
|
+
_validate_optional_list_node(files, "files", _CMD)
|
|
70
75
|
|
|
71
76
|
channel_to_send = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
|
|
72
77
|
allowed_mentions = utils_autorised_mentions(global_mentions, everyone_mention, roles_mentions, users_mentions, reply_mention)
|
|
@@ -74,7 +79,13 @@ async def dshell_send_message(ctx: Message,
|
|
|
74
79
|
if channel_to_send is None:
|
|
75
80
|
raise Exception(f'Channel {channel} not found!')
|
|
76
81
|
|
|
82
|
+
if files is not None:
|
|
83
|
+
for file in files:
|
|
84
|
+
_validate_required_file_node(file, "file", _CMD)
|
|
77
85
|
|
|
86
|
+
final_files: list[File] = []
|
|
87
|
+
for file in files:
|
|
88
|
+
final_files.append(File(fp=file.content, filename=file.filename, description=file.description, spoiler=file.spoiler))
|
|
78
89
|
|
|
79
90
|
_validate_optional_embed(embeds, "Embeds", _CMD)
|
|
80
91
|
|
|
@@ -90,7 +101,8 @@ async def dshell_send_message(ctx: Message,
|
|
|
90
101
|
delete_after=delete,
|
|
91
102
|
embeds=embeds,
|
|
92
103
|
allowed_mentions=allowed_mentions,
|
|
93
|
-
view=view
|
|
104
|
+
view=view,
|
|
105
|
+
files=final_files)
|
|
94
106
|
|
|
95
107
|
cached_messages = dshell_cached_messages.get()
|
|
96
108
|
cached_messages[sended_message.id] = sended_message
|
|
@@ -108,6 +120,7 @@ async def dshell_respond_message(ctx: Message,
|
|
|
108
120
|
users_mentions: bool = True,
|
|
109
121
|
reply_mention: bool = False,
|
|
110
122
|
delete=None,
|
|
123
|
+
files: Optional[ListNode] = None,
|
|
111
124
|
embeds=None):
|
|
112
125
|
"""
|
|
113
126
|
Responds to a message on Discord
|
|
@@ -121,11 +134,21 @@ async def dshell_respond_message(ctx: Message,
|
|
|
121
134
|
_validate_required_bool(roles_mentions, "Roles mentions", _CMD)
|
|
122
135
|
_validate_required_bool(users_mentions, "Users mentions", _CMD)
|
|
123
136
|
_validate_required_bool(reply_mention, "Reply mention", _CMD)
|
|
137
|
+
_validate_optional_list_node(files, "files", _CMD)
|
|
124
138
|
|
|
125
139
|
respond_message = ctx if message is None else utils_get_message(ctx, message) # builds a reference to the message (even if it doesn't exist)
|
|
126
140
|
autorised_mentions = utils_autorised_mentions(global_mentions, everyone_mention, roles_mentions, users_mentions, reply_mention)
|
|
127
141
|
mention_author = True if reply_mention else False
|
|
128
142
|
|
|
143
|
+
if files is not None:
|
|
144
|
+
for file in files:
|
|
145
|
+
_validate_required_file_node(file, "file", _CMD)
|
|
146
|
+
|
|
147
|
+
final_files: list[File] = []
|
|
148
|
+
for file in files:
|
|
149
|
+
final_files.append(
|
|
150
|
+
File(fp=file.content, filename=file.filename, description=file.description, spoiler=file.spoiler))
|
|
151
|
+
|
|
129
152
|
_validate_optional_embed(embeds, "Embeds", _CMD)
|
|
130
153
|
|
|
131
154
|
if embeds is None:
|
|
@@ -139,7 +162,8 @@ async def dshell_respond_message(ctx: Message,
|
|
|
139
162
|
mention_author=mention_author,
|
|
140
163
|
allowed_mentions=autorised_mentions,
|
|
141
164
|
delete_after=delete,
|
|
142
|
-
embeds=embeds
|
|
165
|
+
embeds=embeds,
|
|
166
|
+
files=final_files)
|
|
143
167
|
|
|
144
168
|
cached_messages = dshell_cached_messages.get()
|
|
145
169
|
cached_messages[sended_message.id] = sended_message
|
|
@@ -179,7 +203,7 @@ async def dshell_purge_message(ctx: Message, message_number: int, channel: Optio
|
|
|
179
203
|
await purge_channel.purge(limit=message_number, reason=reason)
|
|
180
204
|
|
|
181
205
|
|
|
182
|
-
async def dshell_edit_message(ctx: Message, message, new_content=None, embeds=None, view=None) -> int:
|
|
206
|
+
async def dshell_edit_message(ctx: Message, message, new_content=None, embeds=None, view=None, files=None) -> int:
|
|
183
207
|
"""
|
|
184
208
|
Edits a message
|
|
185
209
|
"""
|
|
@@ -188,8 +212,17 @@ async def dshell_edit_message(ctx: Message, message, new_content=None, embeds=No
|
|
|
188
212
|
edit_message = utils_get_message(ctx, message)
|
|
189
213
|
|
|
190
214
|
_validate_optional_embed(embeds, "Embeds", _CMD)
|
|
191
|
-
|
|
192
215
|
_validate_optional_view(view, "View", _CMD)
|
|
216
|
+
_validate_optional_list_node(files, "files", _CMD)
|
|
217
|
+
|
|
218
|
+
if files is not None:
|
|
219
|
+
for file in files:
|
|
220
|
+
_validate_required_file_node(file, "file", _CMD)
|
|
221
|
+
|
|
222
|
+
final_files: list[File] = []
|
|
223
|
+
for file in files:
|
|
224
|
+
final_files.append(
|
|
225
|
+
File(fp=file.content, filename=file.filename, description=file.description, spoiler=file.spoiler))
|
|
193
226
|
|
|
194
227
|
if embeds is None:
|
|
195
228
|
embeds = ListNode([])
|
|
@@ -197,7 +230,7 @@ async def dshell_edit_message(ctx: Message, message, new_content=None, embeds=No
|
|
|
197
230
|
elif isinstance(embeds, Embed):
|
|
198
231
|
embeds = ListNode([embeds])
|
|
199
232
|
|
|
200
|
-
await edit_message.edit(content=new_content, embeds=embeds, view=view)
|
|
233
|
+
await edit_message.edit(content=new_content, embeds=embeds, view=view, files=final_files)
|
|
201
234
|
|
|
202
235
|
return edit_message.id
|
|
203
236
|
|
|
@@ -14,11 +14,13 @@ __all__ = [
|
|
|
14
14
|
"_validate_optional_code_node",
|
|
15
15
|
"_validate_optional_list_node",
|
|
16
16
|
"_validate_optional_eval_group_node",
|
|
17
|
+
"_validate_optional_file_node",
|
|
17
18
|
"_validate_required_bool",
|
|
18
19
|
"_validate_required_list_node",
|
|
19
20
|
"_validate_required_int",
|
|
20
21
|
"_validate_required_string",
|
|
21
22
|
"_validate_required_dict",
|
|
23
|
+
"_validate_required_file_node",
|
|
22
24
|
"_validate_missing_or_type",
|
|
23
25
|
"_validate_not_none",
|
|
24
26
|
"_validate_has_attribute",
|
|
@@ -153,6 +155,19 @@ def _validate_optional_list_node(value, param_name: str, command_name: str):
|
|
|
153
155
|
if value is not None and not isinstance(value, ListNode):
|
|
154
156
|
raise TypeError(f"[{command_name}] -> {param_name} must be a list, not {type(value).__name__}")
|
|
155
157
|
|
|
158
|
+
def _validate_optional_file_node(value, param_name: str, command_name: str):
|
|
159
|
+
"""
|
|
160
|
+
Validate that a optional value is a FileNode type.
|
|
161
|
+
:param value: The value to validate
|
|
162
|
+
:param param_name: The parameter name for error messages
|
|
163
|
+
:param command_name: The command name for error messages (optional)
|
|
164
|
+
:raises TypeError: If the value is not a FileNode
|
|
165
|
+
"""
|
|
166
|
+
from ...DshellParser.ast_nodes import AttachmentNode
|
|
167
|
+
|
|
168
|
+
if value is not None and not isinstance(value, AttachmentNode):
|
|
169
|
+
raise TypeError(f"[{command_name}] -> {param_name} must be a FileNode, not {type(value).__name__}")
|
|
170
|
+
|
|
156
171
|
|
|
157
172
|
# Required parameter validation functions
|
|
158
173
|
|
|
@@ -217,6 +232,21 @@ def _validate_required_dict(value, param_name: str, command_name: str):
|
|
|
217
232
|
if not isinstance(value, dict):
|
|
218
233
|
raise TypeError(f"[{command_name}] -> {param_name} must be a dict, not {type(value).__name__}")
|
|
219
234
|
|
|
235
|
+
def _validate_required_file_node(value, param_name: str, command_name: str):
|
|
236
|
+
"""
|
|
237
|
+
Validate that a required value is a FileNode type.
|
|
238
|
+
:param value: The value to validate
|
|
239
|
+
:param param_name: The parameter name for error messages
|
|
240
|
+
:param command_name: The command name for error messages (optional)
|
|
241
|
+
:raises TypeError: If the value is not a FileNode
|
|
242
|
+
"""
|
|
243
|
+
from ...DshellParser.ast_nodes import AttachmentNode
|
|
244
|
+
|
|
245
|
+
if not isinstance(value, AttachmentNode):
|
|
246
|
+
raise TypeError(f"[{command_name}] -> {param_name} must be a FileNode, not {type(value).__name__}")
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
220
250
|
|
|
221
251
|
# Validation functions for _MissingSentinel or other types
|
|
222
252
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
from Dshell.full_import import Any, randint, Optional, Union
|
|
1
|
+
from Dshell.full_import import (Any, randint, Optional, Union, Attachment,
|
|
2
|
+
HTTPException, Forbidden)
|
|
2
3
|
from ..DshellTokenizer.dshell_token_type import Token
|
|
4
|
+
from inspect import iscoroutinefunction
|
|
3
5
|
|
|
4
6
|
__all__ = [
|
|
5
7
|
'ASTNode',
|
|
@@ -30,7 +32,9 @@ __all__ = [
|
|
|
30
32
|
'UiButtonNode',
|
|
31
33
|
'UiSelectNode',
|
|
32
34
|
'OptionUiSelectNode',
|
|
33
|
-
'ScanNode'
|
|
35
|
+
'ScanNode',
|
|
36
|
+
'AttachmentNode',
|
|
37
|
+
'FileNode'
|
|
34
38
|
]
|
|
35
39
|
|
|
36
40
|
|
|
@@ -943,3 +947,110 @@ class ListNode(ASTNode):
|
|
|
943
947
|
|
|
944
948
|
def __repr__(self):
|
|
945
949
|
return f"<LIST> - {self.iterable}"
|
|
950
|
+
|
|
951
|
+
class AttachmentNode(ASTNode):
|
|
952
|
+
|
|
953
|
+
def __init__(self, attachment: Attachment):
|
|
954
|
+
super().__init__(0)
|
|
955
|
+
self.attachment = attachment
|
|
956
|
+
|
|
957
|
+
async def read(self):
|
|
958
|
+
"""
|
|
959
|
+
Lit l'intégralité du fichier et le décode en utf-8
|
|
960
|
+
:return:
|
|
961
|
+
"""
|
|
962
|
+
try:
|
|
963
|
+
filebytes: bytes = await self.attachment.read()
|
|
964
|
+
return filebytes.decode(encoding="utf-8", errors="ignore")
|
|
965
|
+
except Forbidden:
|
|
966
|
+
return b"The file is not accessible, the bot does not have permission to access it"
|
|
967
|
+
except HTTPException:
|
|
968
|
+
return b"Download file failed"
|
|
969
|
+
except Exception:
|
|
970
|
+
return b"An error occurred in the file read action"
|
|
971
|
+
|
|
972
|
+
async def read_sector(self, sector: int):
|
|
973
|
+
"""
|
|
974
|
+
Lit tout le fichier secteur par secteur en les décodant en utf-8
|
|
975
|
+
:return:
|
|
976
|
+
"""
|
|
977
|
+
try:
|
|
978
|
+
async for chunk in await self.attachment.read_chunked(sector):
|
|
979
|
+
yield chunk.decode(encoding="utf-8", errors="ignore")
|
|
980
|
+
except Forbidden:
|
|
981
|
+
yield b"The file is not accessible, the bot does not have permission to access it"
|
|
982
|
+
except HTTPException:
|
|
983
|
+
yield b"Download file failed"
|
|
984
|
+
except Exception:
|
|
985
|
+
yield b"An error occurred in the file read action"
|
|
986
|
+
|
|
987
|
+
def content_type(self):
|
|
988
|
+
return self.attachment.content_type
|
|
989
|
+
|
|
990
|
+
def desc(self):
|
|
991
|
+
return self.attachment.description
|
|
992
|
+
|
|
993
|
+
def description(self):
|
|
994
|
+
return self.attachment.description
|
|
995
|
+
|
|
996
|
+
def duration(self):
|
|
997
|
+
return self.attachment.duration_secs
|
|
998
|
+
|
|
999
|
+
def ephemeral(self):
|
|
1000
|
+
return self.attachment.ephemeral
|
|
1001
|
+
|
|
1002
|
+
def url(self):
|
|
1003
|
+
return self.attachment.url
|
|
1004
|
+
|
|
1005
|
+
def filename(self):
|
|
1006
|
+
return self.attachment.filename
|
|
1007
|
+
|
|
1008
|
+
def size(self):
|
|
1009
|
+
return self.attachment.size
|
|
1010
|
+
|
|
1011
|
+
def title(self):
|
|
1012
|
+
return self.attachment.title
|
|
1013
|
+
|
|
1014
|
+
def height(self):
|
|
1015
|
+
return self.attachment.height
|
|
1016
|
+
|
|
1017
|
+
def width(self):
|
|
1018
|
+
return self.attachment.width
|
|
1019
|
+
|
|
1020
|
+
def signature(self):
|
|
1021
|
+
return self.attachment.hm
|
|
1022
|
+
|
|
1023
|
+
def call(self, attribute: str):
|
|
1024
|
+
"""
|
|
1025
|
+
Permet d'appeler une méthode de l'attachment
|
|
1026
|
+
:param attribute: nom de la méthode à appeler
|
|
1027
|
+
:return: le résultat de la méthode appelée
|
|
1028
|
+
"""
|
|
1029
|
+
if hasattr(self, attribute) and attribute != 'call':
|
|
1030
|
+
attr = getattr(self, attribute)
|
|
1031
|
+
if not iscoroutinefunction(attr) and callable(attr):
|
|
1032
|
+
return attr()
|
|
1033
|
+
else:
|
|
1034
|
+
raise AttributeError(f"'{attribute}' is not a callable method of the attachment !")
|
|
1035
|
+
else:
|
|
1036
|
+
raise AttributeError(f"The attachment does not have an attribute named '{attribute}' !")
|
|
1037
|
+
|
|
1038
|
+
class FileNode(ASTNode):
|
|
1039
|
+
def __init__(self, name: Optional[str], description: Optional[str] = None, spoiler: bool = False):
|
|
1040
|
+
super().__init__(0)
|
|
1041
|
+
self.name = name
|
|
1042
|
+
self.description = description
|
|
1043
|
+
self.spoiler = spoiler
|
|
1044
|
+
self.content: bytearray = bytearray("", "utf-8")
|
|
1045
|
+
|
|
1046
|
+
def write(self, content: bytearray, append: bool):
|
|
1047
|
+
if append:
|
|
1048
|
+
self.content += content
|
|
1049
|
+
else:
|
|
1050
|
+
self.content = content
|
|
1051
|
+
|
|
1052
|
+
def read(self):
|
|
1053
|
+
return self.content.decode(encoding="utf-8", errors="ignore")
|
|
1054
|
+
|
|
1055
|
+
def size(self):
|
|
1056
|
+
return len(self.content)
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellParser/dshell_parser.py
RENAMED
|
@@ -30,7 +30,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
30
30
|
first_token_line = tokens_by_line[0] # get the first token of the line
|
|
31
31
|
last_block = blocks[-1]
|
|
32
32
|
|
|
33
|
-
line =
|
|
33
|
+
line = first_token_line.position[0]
|
|
34
34
|
|
|
35
35
|
if first_token_line.type == DTT.COMMAND: # if the token is a command
|
|
36
36
|
body = tokens_by_line[1:] # get its arguments
|
|
@@ -42,7 +42,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
42
42
|
elif first_token_line.type == DTT.KEYWORD: # if it's a keyword
|
|
43
43
|
|
|
44
44
|
if first_token_line.value == 'if': # if it's a condition
|
|
45
|
-
if
|
|
45
|
+
if len_tokens_by_line_since_command_name <= 0:
|
|
46
46
|
raise SyntaxError(f'[IF] Take one or more arguments on line {first_token_line.position} !')
|
|
47
47
|
|
|
48
48
|
if_node = IfNode(condition=tokens_by_line[1:],
|
|
@@ -67,7 +67,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
67
67
|
elif first_token_line.value == 'elif':
|
|
68
68
|
if not isinstance(last_block, (IfNode, ElifNode)):
|
|
69
69
|
raise SyntaxError(f'[ELIF] No conditional bloc open on line {first_token_line.position} !')
|
|
70
|
-
if
|
|
70
|
+
if len_tokens_by_line_since_command_name <= 0:
|
|
71
71
|
raise SyntaxError(f'[ELIF] Take one or more arguments on line {first_token_line.position} !')
|
|
72
72
|
elif_node = ElifNode(condition=tokens_by_line[1:], body=[],
|
|
73
73
|
parent=last_block if isinstance(last_block, IfNode) else last_block.parent, line=line)
|
|
@@ -197,7 +197,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
197
197
|
return blocks, pointer
|
|
198
198
|
|
|
199
199
|
elif first_token_line.value == 'eval':
|
|
200
|
-
if
|
|
200
|
+
if len_tokens_by_line_since_command_name < 1:
|
|
201
201
|
raise SyntaxError(f"[EVAL] take one or more arguments on line {first_token_line.position}")
|
|
202
202
|
|
|
203
203
|
if tokens_by_line[1].type != DTT.IDENT:
|
|
@@ -210,7 +210,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
210
210
|
elif first_token_line.value == 'return':
|
|
211
211
|
if not isinstance(last_block, CodeNode):
|
|
212
212
|
raise SyntaxError(f"[RETURN] No code open on line {first_token_line.position} !")
|
|
213
|
-
if
|
|
213
|
+
if len_tokens_by_line_since_command_name < 1:
|
|
214
214
|
raise SyntaxError(f"[RETURN] take one or more arguments on line {first_token_line.position}")
|
|
215
215
|
|
|
216
216
|
return_node = ReturnNode(body=tokens_by_line[1:], line=line)
|
|
@@ -222,7 +222,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
222
222
|
|
|
223
223
|
elif first_token_line.value == '#end': # node pour arrêter le programme si elle est rencontré
|
|
224
224
|
error_message = True
|
|
225
|
-
if
|
|
225
|
+
if len_tokens_by_line_since_command_name > 0:
|
|
226
226
|
if tokens_by_line[1].type != DTT.BOOL:
|
|
227
227
|
raise TypeError(f'[#END] the variable given must be a boolean, not {tokens_by_line[1].type}')
|
|
228
228
|
else:
|
|
@@ -235,7 +235,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
235
235
|
elif first_token_line.type == DTT.DISCORD_KEYWORD:
|
|
236
236
|
|
|
237
237
|
if first_token_line.value == 'embed':
|
|
238
|
-
if
|
|
238
|
+
if len_tokens_by_line_since_command_name <= 0:
|
|
239
239
|
raise SyntaxError(f'[EMBED] Take one or more arguments on line {first_token_line.position} !')
|
|
240
240
|
if tokens_by_line[1].type != DTT.IDENT:
|
|
241
241
|
raise TypeError(f'[EMBED] the variable given must be a ident, '
|
|
@@ -254,7 +254,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
254
254
|
return blocks, pointer
|
|
255
255
|
|
|
256
256
|
elif first_token_line.value == 'field':
|
|
257
|
-
if
|
|
257
|
+
if len_tokens_by_line_since_command_name <= 0:
|
|
258
258
|
raise SyntaxError(f'[FIELD] Take one or more arguments on line {first_token_line.position} !')
|
|
259
259
|
if not isinstance(last_block, EmbedNode):
|
|
260
260
|
raise SyntaxError(f'[FIELD] No embed open on line {first_token_line.position} !')
|
|
@@ -262,7 +262,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
262
262
|
last_block.fields.append(FieldEmbedNode(tokens_by_line[1:], line=line))
|
|
263
263
|
|
|
264
264
|
elif first_token_line.value in ('perm', 'permission'):
|
|
265
|
-
if
|
|
265
|
+
if len_tokens_by_line_since_command_name <= 0:
|
|
266
266
|
raise SyntaxError(f'[PERM] Take one argument on line {first_token_line.position} !')
|
|
267
267
|
if tokens_by_line[1].type != DTT.IDENT:
|
|
268
268
|
raise TypeError(f'[PERM] the variable given must be a ident, '
|
|
@@ -281,7 +281,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
281
281
|
return blocks, pointer
|
|
282
282
|
|
|
283
283
|
elif first_token_line.value == 'button':
|
|
284
|
-
if
|
|
284
|
+
if len_tokens_by_line_since_command_name <= 0:
|
|
285
285
|
raise SyntaxError(f'[BUTTON] Take one or more arguments on line {first_token_line.position} !')
|
|
286
286
|
if tokens_by_line[1].type != DTT.IDENT:
|
|
287
287
|
raise TypeError(f'[BUTTON] the variable given must be a ident, '
|
|
@@ -300,7 +300,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
300
300
|
return blocks, pointer
|
|
301
301
|
|
|
302
302
|
elif first_token_line.value == 'select':
|
|
303
|
-
if
|
|
303
|
+
if len_tokens_by_line_since_command_name <= 0:
|
|
304
304
|
raise SyntaxError(f'[SELECT] Take one or more arguments on line {first_token_line.position} !')
|
|
305
305
|
if tokens_by_line[1].type != DTT.IDENT:
|
|
306
306
|
raise TypeError(f'[SELECT] the variable given must be a ident, '
|
|
@@ -319,7 +319,7 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
319
319
|
return blocks, pointer
|
|
320
320
|
|
|
321
321
|
elif first_token_line.value == 'option':
|
|
322
|
-
if
|
|
322
|
+
if len_tokens_by_line_since_command_name <= 0:
|
|
323
323
|
raise SyntaxError(f'[OPTION] Take one or more arguments on line {first_token_line.position} !')
|
|
324
324
|
if not isinstance(last_block, UiSelectNode):
|
|
325
325
|
raise SyntaxError(f'[OPTION] No UISelect open on line {first_token_line.position} !')
|
|
@@ -329,10 +329,19 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
329
329
|
############################## AUTRE ##############################
|
|
330
330
|
|
|
331
331
|
elif first_token_line.type in DTT_DATA: # if the line starts with a data token, we consider it as a command with an implicit "sm" name
|
|
332
|
-
for token in tokens_by_line:
|
|
333
332
|
|
|
334
|
-
|
|
335
|
-
|
|
333
|
+
if (len_tokens_by_line_since_command_name > 0 and
|
|
334
|
+
tokens_by_line[1].type in (DTT.LOGIC_OPERATOR, DTT.MATHS_OPERATOR, DTT.LOGIC_WORD_OPERATOR)):
|
|
335
|
+
|
|
336
|
+
new_content = [first_token_line]
|
|
337
|
+
new_content.extend(tokens_by_line[1:])
|
|
338
|
+
last_block.body.append(VarNode(first_token_line, new_content, line=line))
|
|
339
|
+
|
|
340
|
+
else:
|
|
341
|
+
for token in tokens_by_line:
|
|
342
|
+
|
|
343
|
+
if token.type in DTT_DATA:
|
|
344
|
+
last_block.body.append(CommandNode(name='sm', body=ArgsCommandNode([token], line=line), line=line))
|
|
336
345
|
|
|
337
346
|
else:
|
|
338
347
|
last_block.body += tokens_by_line
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellTokenizer/dshell_keywords.py
RENAMED
|
@@ -11,7 +11,7 @@ __all__ = [
|
|
|
11
11
|
from ..DISCORD_COMMANDS import *
|
|
12
12
|
|
|
13
13
|
from Dshell.full_import import Callable
|
|
14
|
-
|
|
14
|
+
from ..DISCORD_COMMANDS.dshell_file import dshell_read_file, dshell_write_file, dshell_get_message_files
|
|
15
15
|
|
|
16
16
|
dshell_keyword: set[str] = {
|
|
17
17
|
'if', 'else', 'elif', 'loop', '#end', 'var', '#loop', '#if', 'sleep', 'param', '#param', 'code', '#code', 'eval', 'return'
|
|
@@ -81,6 +81,11 @@ dshell_commands: dict[str, Callable] = {
|
|
|
81
81
|
## Pastbin command
|
|
82
82
|
"gp": dshell_get_pastbin, # get pastbin
|
|
83
83
|
|
|
84
|
+
## Files
|
|
85
|
+
"rf": dshell_read_file,
|
|
86
|
+
"wf": dshell_write_file,
|
|
87
|
+
"gmfs": dshell_get_message_files,
|
|
88
|
+
|
|
84
89
|
## Discord commands
|
|
85
90
|
"sm": dshell_send_message, # send message
|
|
86
91
|
"spm": dshell_send_private_message, # send private message
|
|
@@ -201,7 +206,8 @@ dshell_logical_operators: dict[str, tuple[Callable, int, int, int]] = {
|
|
|
201
206
|
r"<": (lambda a, b: a < b, 4, 2, 2),
|
|
202
207
|
r">": (lambda a, b: a > b, 4, 2, 2),
|
|
203
208
|
r"!": (lambda a: not a, 3, 1, 1),
|
|
204
|
-
r"?": (lambda condition, first_choice, second_choice: first_choice if condition else second_choice, 1, 3, 3)
|
|
209
|
+
r"?": (lambda condition, first_choice, second_choice: first_choice if condition else second_choice, 1, 3, 3),
|
|
210
|
+
r".": (lambda target, attribute: target.call(attribute) if hasattr(target, attribute) and hasattr(target, 'call') else None, 9, 2, 2), # attribute access operator
|
|
205
211
|
|
|
206
212
|
}
|
|
207
213
|
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellTokenizer/dshell_tokenizer.py
RENAMED
|
@@ -55,12 +55,13 @@ table_regex: dict[DTT, Pattern] = {
|
|
|
55
55
|
DTT.KEYWORD: compile(rf"(?<!\w)(#?{'|'.join(dshell_keyword)})(?!\w)"),
|
|
56
56
|
DTT.DISCORD_KEYWORD: compile(rf"(?<!\w|-)(#?{'|'.join(dshell_discord_keyword)})(?!\w|-)", flags=IGNORECASE),
|
|
57
57
|
DTT.COMMAND: compile(rf"\b({'|'.join(dshell_commands.keys())})\b", flags=IGNORECASE),
|
|
58
|
-
DTT.MATHS_OPERATOR: compile(rf"({'|'.join([escape(i) for i in dshell_mathematical_operators.keys()])})"),
|
|
59
|
-
DTT.LOGIC_OPERATOR: compile(rf"({'|'.join([escape(i) for i in dshell_logical_operators.keys()])})"),
|
|
60
|
-
DTT.LOGIC_WORD_OPERATOR: compile(rf"(?:^|\s)({'|'.join([escape(i) for i in dshell_logical_word_operators.keys()])})(?:$|\s)"),
|
|
61
58
|
DTT.FLOAT: compile(r"(\d+\.\d+)"),
|
|
62
59
|
DTT.HEXA: compile(r"(0[Xx][0-9a-fA-F]+)"),
|
|
63
60
|
DTT.INT: compile(r"(\d+)"),
|
|
61
|
+
DTT.MATHS_OPERATOR: compile(rf"({'|'.join([escape(i) for i in dshell_mathematical_operators.keys()])})"),
|
|
62
|
+
DTT.LOGIC_OPERATOR: compile(rf"({'|'.join([escape(i) for i in dshell_logical_operators.keys()])})"),
|
|
63
|
+
DTT.LOGIC_WORD_OPERATOR: compile(
|
|
64
|
+
rf"(?:^|\s)({'|'.join([escape(i) for i in dshell_logical_word_operators.keys()])})(?:$|\s)"),
|
|
64
65
|
DTT.BOOL: compile(r"(True|False)", flags=IGNORECASE),
|
|
65
66
|
DTT.NONE: compile(r"(None)", flags=IGNORECASE),
|
|
66
67
|
DTT.IDENT: compile(rf"([A-Za-z0-9_]+)"),
|
|
@@ -7,9 +7,7 @@ from datetime import timedelta, datetime, UTC
|
|
|
7
7
|
from requests import get
|
|
8
8
|
|
|
9
9
|
from discord.ui import Button, Select
|
|
10
|
-
from discord import
|
|
11
|
-
CategoryChannel, VoiceChannel, TextChannel, Thread, PartialMessage, NotFound, ForumChannel, Colour,
|
|
12
|
-
Embed, AutoShardedBot, ComponentType, AllowedMentions)
|
|
10
|
+
from discord import *
|
|
13
11
|
from discord.abc import PrivateChannel
|
|
14
12
|
from discord.utils import get, _MissingSentinel
|
|
15
13
|
from contextvars import ContextVar
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/dshellInterpreter.egg-info/SOURCES.txt
RENAMED
|
@@ -7,6 +7,7 @@ Dshell/regex_test.py
|
|
|
7
7
|
Dshell/DISCORD_COMMANDS/__init__.py
|
|
8
8
|
Dshell/DISCORD_COMMANDS/dshell_channel.py
|
|
9
9
|
Dshell/DISCORD_COMMANDS/dshell_embed.py
|
|
10
|
+
Dshell/DISCORD_COMMANDS/dshell_file.py
|
|
10
11
|
Dshell/DISCORD_COMMANDS/dshell_interaction.py
|
|
11
12
|
Dshell/DISCORD_COMMANDS/dshell_member.py
|
|
12
13
|
Dshell/DISCORD_COMMANDS/dshell_message.py
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="dshellInterpreter",
|
|
8
|
-
version="1.1.4.
|
|
8
|
+
version="1.1.4.4",
|
|
9
9
|
author="Chronos",
|
|
10
10
|
author_email="vagabonwalybi@gmail.com",
|
|
11
11
|
description="A Discord bot interpreter for creating custom commands and automations.",
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_channel.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_embed.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_member.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_role.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/dshell_ui.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DISCORD_COMMANDS/utils/utils_list.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/__init__.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/cached_messages.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellInterpreteur/dshell_scope.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellPreProcess/dshell_preprocess.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/Dshell/DshellTokenizer/dshell_token_type.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/dshellInterpreter.egg-info/requires.txt
RENAMED
|
File without changes
|
{dshellinterpreter-1.1.4.2 → dshellinterpreter-1.1.4.4}/dshellInterpreter.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|