dshellInterpreter 1.2.0.15__tar.gz → 1.2.0.17__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.2.0.17/Dshell/DISCORD_COMMANDS/dshell_ui.py +519 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_embed.py +1 -1
- {dshellinterpreter-1.2.0.15/dshellInterpreter.egg-info → dshellinterpreter-1.2.0.17}/PKG-INFO +1 -1
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17/dshellInterpreter.egg-info}/PKG-INFO +1 -1
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/setup.py +1 -1
- dshellinterpreter-1.2.0.15/Dshell/DISCORD_COMMANDS/dshell_ui.py +0 -361
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/__init__.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_channel.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_embed.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_file.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_interaction.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_member.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_message.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_role.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/__init__.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_file.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_global.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_list.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_member.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_message.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_numbers.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_permissions.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_string.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_thread.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/utils_type_validation.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/__init__.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/cached_messages.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/dshell_arguments.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/dshell_global_variables.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/dshell_interpreter.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/dshell_scope.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/errors.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/utils_interpreter.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellParser/__init__.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellParser/ast_nodes.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellParser/dshell_parser.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellParser/errors.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellPreProcess/__init__.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellPreProcess/dshell_preprocess.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellTokenizer/__init__.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellTokenizer/dshell_keywords.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellTokenizer/dshell_token_type.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellTokenizer/dshell_tokenizer.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/__init__.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/full_import.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/regex_test.py +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/LICENSE +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/README.md +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/dshellInterpreter.egg-info/SOURCES.txt +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/dshellInterpreter.egg-info/dependency_links.txt +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/dshellInterpreter.egg-info/requires.txt +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/dshellInterpreter.egg-info/top_level.txt +0 -0
- {dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/setup.cfg +0 -0
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
from Dshell.full_import import (ButtonStyle,
|
|
2
|
+
PrivateChannel,
|
|
3
|
+
Interaction,
|
|
4
|
+
ui,
|
|
5
|
+
MISSING,
|
|
6
|
+
EasyModifiedViews,
|
|
7
|
+
CustomIDNotFound,
|
|
8
|
+
SelectMenu,
|
|
9
|
+
ComponentType,
|
|
10
|
+
random)
|
|
11
|
+
|
|
12
|
+
from ..DshellParser.ast_nodes import UiSelectNode, UiButtonNode, OptionUiSelectNode, ListNode, StrNode, IntNode, BoolNode
|
|
13
|
+
|
|
14
|
+
from ..DshellInterpreteur.utils_interpreter import regroupe_commandes
|
|
15
|
+
|
|
16
|
+
from ..DshellInterpreteur.dshell_scope import new_scope
|
|
17
|
+
|
|
18
|
+
from Dshell.full_import import Any, TYPE_CHECKING, Union
|
|
19
|
+
|
|
20
|
+
from .utils.utils_type_validation import (_validate_optional_code_node,
|
|
21
|
+
_validate_optional_int,
|
|
22
|
+
_validate_optional_string)
|
|
23
|
+
|
|
24
|
+
from .utils.utils_global import utils_refactor_emoji
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
ButtonStyleValues: set = {i.name for i in ButtonStyle}
|
|
31
|
+
SelectSyleValues: dict = {'string': ComponentType.string_select,
|
|
32
|
+
'role': ComponentType.role_select,
|
|
33
|
+
'user': ComponentType.user_select,
|
|
34
|
+
'mention': ComponentType.mentionable_select,
|
|
35
|
+
'channel': ComponentType.channel_select}
|
|
36
|
+
|
|
37
|
+
async def build_ui_button_parameters(ui_button_node: UiButtonNode, interpreter: "DshellInterpreteur"):
|
|
38
|
+
"""
|
|
39
|
+
Builds the parameters for a UI component from the UiNode.
|
|
40
|
+
Can accept buttons and select menus.
|
|
41
|
+
:param ui_node:
|
|
42
|
+
:param interpreter:
|
|
43
|
+
:return:
|
|
44
|
+
"""
|
|
45
|
+
regrouped_parameters = await regroupe_commandes(ui_button_node.body, interpreter, normalise=True)
|
|
46
|
+
args_button: dict[str, list[Any]] = regrouped_parameters.get_dict_parameters()
|
|
47
|
+
|
|
48
|
+
code = args_button.pop('code', None)
|
|
49
|
+
style = args_button.pop('style', 'primary').lower()
|
|
50
|
+
custom_id = args_button.pop('custom_id', 'ui_button_'+str(random()))
|
|
51
|
+
row = args_button.pop('row', 0)
|
|
52
|
+
emoji = utils_refactor_emoji(args_button.pop('emoji', None))
|
|
53
|
+
|
|
54
|
+
_validate_optional_code_node(code, "Button code", "build_ui_button")
|
|
55
|
+
|
|
56
|
+
if not isinstance(custom_id, str):
|
|
57
|
+
raise TypeError(f"Button custom_id must be a string, not {type(custom_id)} !")
|
|
58
|
+
|
|
59
|
+
if style not in ButtonStyleValues:
|
|
60
|
+
raise ValueError(f"Button style must be one of {', '.join(ButtonStyleValues)}, not '{style}' !")
|
|
61
|
+
|
|
62
|
+
args_button['custom_id'] = custom_id
|
|
63
|
+
args_button['row'] = row
|
|
64
|
+
args_button['style'] = ButtonStyle[style]
|
|
65
|
+
args_button['emoji'] = emoji
|
|
66
|
+
args = args_button.pop('*', ())
|
|
67
|
+
yield args, args_button, code
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
async def build_ui_select_parameters(ui_select_node: UiSelectNode, interpreter: "DshellInterpreteur"):
|
|
71
|
+
"""
|
|
72
|
+
Builds the parameters for a UI select menu from the UiNode.
|
|
73
|
+
:param ui_select_node:
|
|
74
|
+
:param interpreter:
|
|
75
|
+
:return:
|
|
76
|
+
"""
|
|
77
|
+
regrouped_parameters = await regroupe_commandes(ui_select_node.body, interpreter, normalise=True)
|
|
78
|
+
args_select: dict[str, list[Any]] = regrouped_parameters.get_dict_parameters()
|
|
79
|
+
|
|
80
|
+
code = args_select.pop('code', None)
|
|
81
|
+
custom_id = args_select.pop('custom_id', 'ui_select_'+str(random()))
|
|
82
|
+
select_type = args_select.pop('type', 'string').lower()
|
|
83
|
+
|
|
84
|
+
disabled = args_select.get('disabled', False)
|
|
85
|
+
max_values = args_select.get('max', 1)
|
|
86
|
+
min_values = args_select.get('min', 1)
|
|
87
|
+
placeholder = args_select.get('placeholder', "")
|
|
88
|
+
row = args_select.pop('row', 0)
|
|
89
|
+
|
|
90
|
+
_validate_optional_code_node(code, "Select code", "build_ui_select")
|
|
91
|
+
|
|
92
|
+
if not isinstance(custom_id, str):
|
|
93
|
+
raise TypeError(f"Select custom_id must be a string, not {type(custom_id)} !")
|
|
94
|
+
|
|
95
|
+
if select_type is None or not isinstance(select_type, str) or select_type not in SelectSyleValues:
|
|
96
|
+
raise TypeError(f"Select type must be a string, not {type(select_type)} !")
|
|
97
|
+
|
|
98
|
+
if not isinstance(disabled, bool):
|
|
99
|
+
raise TypeError(f"Select disabled must be a bool, not {type(disabled)} !")
|
|
100
|
+
|
|
101
|
+
if not isinstance(max_values, int):
|
|
102
|
+
raise TypeError(f"Select max_values must be an int, not {type(max_values)} !")
|
|
103
|
+
|
|
104
|
+
if not isinstance(min_values, int):
|
|
105
|
+
raise TypeError(f"Select min_values must be an int, not {type(min_values)} !")
|
|
106
|
+
|
|
107
|
+
if not isinstance(placeholder, str):
|
|
108
|
+
raise TypeError(f"Select placeholder must be a string, not {type(placeholder)} !")
|
|
109
|
+
|
|
110
|
+
_validate_optional_int(row, "Select row", "build_ui_select")
|
|
111
|
+
|
|
112
|
+
args_select["disabled"] = disabled
|
|
113
|
+
args_select["max_values"] = max_values
|
|
114
|
+
args_select["min_values"] = min_values
|
|
115
|
+
args_select["options"] = await build_ui_select_options(ui_select_node.options, interpreter)
|
|
116
|
+
args_select["placeholder"] = placeholder
|
|
117
|
+
args_select["row"] = row
|
|
118
|
+
args_select["type"] = SelectSyleValues[select_type]
|
|
119
|
+
args_select['custom_id'] = custom_id
|
|
120
|
+
args = args_select.pop('*', ())
|
|
121
|
+
|
|
122
|
+
yield args, args_select, code
|
|
123
|
+
|
|
124
|
+
async def build_ui_select_options(option_nodes: list[OptionUiSelectNode], interpreter: "DshellInterpreteur"):
|
|
125
|
+
"""
|
|
126
|
+
Builds the options for a UI select menu from the OptionUiSelectNode.
|
|
127
|
+
:param option_nodes:
|
|
128
|
+
:param interpreter:
|
|
129
|
+
:return:
|
|
130
|
+
"""
|
|
131
|
+
option_results: list[dict[str, Any]] = []
|
|
132
|
+
|
|
133
|
+
for option_node in option_nodes:
|
|
134
|
+
regrouped_parameters = await regroupe_commandes(option_node.body, interpreter, normalise=True)
|
|
135
|
+
args_option: dict[str, list[Any]] = regrouped_parameters.get_dict_parameters()
|
|
136
|
+
|
|
137
|
+
label = args_option.pop('label', None)
|
|
138
|
+
value = args_option.pop('value', MISSING)
|
|
139
|
+
description = args_option.pop('description', None)
|
|
140
|
+
emoji = utils_refactor_emoji(args_option.pop('emoji', None))
|
|
141
|
+
default = args_option.pop('default', False)
|
|
142
|
+
|
|
143
|
+
if label is None or not isinstance(label, str):
|
|
144
|
+
raise TypeError(f"Option label must be a string, not {type(label)} !")
|
|
145
|
+
|
|
146
|
+
if len(label) > 100:
|
|
147
|
+
raise ValueError("Option label must be less than 100 characters !")
|
|
148
|
+
|
|
149
|
+
if value and not isinstance(value, str):
|
|
150
|
+
raise TypeError(f"Option value must be a string, not {type(value)} !")
|
|
151
|
+
|
|
152
|
+
if value and len(value) > 100:
|
|
153
|
+
raise ValueError("Option value must be less than 100 characters !")
|
|
154
|
+
|
|
155
|
+
_validate_optional_string(description, "Option description", "build_ui_option")
|
|
156
|
+
|
|
157
|
+
if description is not None and len(description) > 100:
|
|
158
|
+
raise ValueError("Option description must be less than 100 characters !")
|
|
159
|
+
|
|
160
|
+
_validate_optional_string(emoji, "Option emoji", "build_ui_option")
|
|
161
|
+
|
|
162
|
+
if not isinstance(default, bool):
|
|
163
|
+
raise TypeError(f"Option default must be a bool, not {type(default)} !")
|
|
164
|
+
|
|
165
|
+
option_dict = {
|
|
166
|
+
'label': label,
|
|
167
|
+
'value': value,
|
|
168
|
+
'description': description,
|
|
169
|
+
'emoji': emoji,
|
|
170
|
+
'default': default,
|
|
171
|
+
}
|
|
172
|
+
option_results.append(option_dict)
|
|
173
|
+
|
|
174
|
+
return option_results
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
async def build_ui(ui_node: Union[UiButtonNode, UiSelectNode], interpreter: "DshellInterpreteur") -> EasyModifiedViews:
|
|
178
|
+
"""
|
|
179
|
+
Builds a UI component from the UiNode.
|
|
180
|
+
Can accept buttons and select menus.
|
|
181
|
+
:param ui_node:
|
|
182
|
+
:param interpreter:
|
|
183
|
+
:return:
|
|
184
|
+
"""
|
|
185
|
+
view = EasyModifiedViews()
|
|
186
|
+
|
|
187
|
+
if isinstance(ui_node, UiButtonNode):
|
|
188
|
+
async for _, args_button, code in build_ui_button_parameters(ui_node, interpreter):
|
|
189
|
+
print(args_button)
|
|
190
|
+
b = ui.Button(**args_button)
|
|
191
|
+
view.add_items(b)
|
|
192
|
+
view.set_callable(b.custom_id, _callable=ui_button_callback, data={'code': code, 'interpreter': interpreter})
|
|
193
|
+
|
|
194
|
+
elif isinstance(ui_node, UiSelectNode):
|
|
195
|
+
s = SelectMenu()
|
|
196
|
+
async for _, args_select, code in build_ui_select_parameters(ui_node, interpreter):
|
|
197
|
+
|
|
198
|
+
options = args_select.pop("options", [])
|
|
199
|
+
select_type = args_select.pop("type")
|
|
200
|
+
|
|
201
|
+
if select_type == ComponentType.string_select:
|
|
202
|
+
menu = s.add_string_select_menu(**args_select)
|
|
203
|
+
|
|
204
|
+
for option in options:
|
|
205
|
+
menu.add_option(**option)
|
|
206
|
+
|
|
207
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
208
|
+
|
|
209
|
+
elif select_type == ComponentType.role_select:
|
|
210
|
+
s.add_role_select_menu(**args_select)
|
|
211
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
212
|
+
|
|
213
|
+
elif select_type == ComponentType.user_select:
|
|
214
|
+
s.add_user_select_menu(**args_select)
|
|
215
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
216
|
+
|
|
217
|
+
elif select_type == ComponentType.mentionable_select:
|
|
218
|
+
s.add_mentionable_select_menu(**args_select)
|
|
219
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
220
|
+
|
|
221
|
+
elif select_type == ComponentType.channel_select:
|
|
222
|
+
s.add_channel_select_menu(**args_select)
|
|
223
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
224
|
+
|
|
225
|
+
view.add_items(s)
|
|
226
|
+
|
|
227
|
+
else:
|
|
228
|
+
raise TypeError(f"UI node must be UiButtonNode or UiSelectNode, not {type(ui_node)} !")
|
|
229
|
+
|
|
230
|
+
return view
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
async def rebuild_ui(ui_node: Union[UiButtonNode, UiSelectNode], view: EasyModifiedViews, interpreter: "DshellInterpreteur") -> EasyModifiedViews:
|
|
235
|
+
"""
|
|
236
|
+
Rebuilds a UI component from an existing EasyModifiedViews.
|
|
237
|
+
:param view:
|
|
238
|
+
:param interpreter:
|
|
239
|
+
:return:
|
|
240
|
+
"""
|
|
241
|
+
if isinstance(ui_node, UiButtonNode):
|
|
242
|
+
|
|
243
|
+
async for args, args_button, code in build_ui_button_parameters(ui_node, interpreter):
|
|
244
|
+
try:
|
|
245
|
+
ui: ui.Button = view.get_ui(args_button['custom_id'])
|
|
246
|
+
except CustomIDNotFound:
|
|
247
|
+
raise ValueError(f"Button with custom_id '{args_button['custom_id']}' not found in the view !")
|
|
248
|
+
|
|
249
|
+
ui.label = args_button.get('label', ui.label)
|
|
250
|
+
ui.style = args_button.get('style', ui.style)
|
|
251
|
+
ui.emoji = args_button.get('emoji', ui.emoji)
|
|
252
|
+
ui.disabled = args_button.get('disabled', ui.disabled)
|
|
253
|
+
ui.url = args_button.get('url', ui.url)
|
|
254
|
+
ui.row = args_button.get('row', ui.row)
|
|
255
|
+
new_code = code if code is not None else view.get_callable_data(args_button['custom_id'])['code']
|
|
256
|
+
view.set_callable(args_button['custom_id'], _callable=ui_button_callback, data={'code': new_code, 'interpreter': interpreter})
|
|
257
|
+
|
|
258
|
+
elif isinstance(ui_node, UiSelectNode):
|
|
259
|
+
|
|
260
|
+
async for args, args_select, code in build_ui_select_parameters(ui_select_node=ui_node, interpreter=interpreter):
|
|
261
|
+
try:
|
|
262
|
+
ui: ui.Select = view.get_ui(args_select['custom_id'])
|
|
263
|
+
except CustomIDNotFound:
|
|
264
|
+
raise ValueError(f"Select menu with custom_id '{args_select['custom_id']}' not found in the view !")
|
|
265
|
+
|
|
266
|
+
ui.placeholder = args_select.get('placeholder', ui.placeholder)
|
|
267
|
+
ui.min_values = args_select.get('min_values', ui.min_values)
|
|
268
|
+
ui.max_values = args_select.get('max_values', ui.max_values)
|
|
269
|
+
ui.disabled = args_select.get('disabled', ui.disabled)
|
|
270
|
+
|
|
271
|
+
ui.options.clear()
|
|
272
|
+
options = args_select.pop("options", [])
|
|
273
|
+
for option in options:
|
|
274
|
+
ui.add_option(**option)
|
|
275
|
+
|
|
276
|
+
new_code = code if code is not None else view.get_callable_data(args_select['custom_id'])['code']
|
|
277
|
+
view.set_callable(args_select['custom_id'], _callable=ui_select_callback, data={'code': new_code, 'interpreter': interpreter})
|
|
278
|
+
|
|
279
|
+
return view
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
async def ui_button_callback(button: ui.Button, interaction: Interaction, data: dict[str, Any]):
|
|
283
|
+
"""
|
|
284
|
+
Callback for UI buttons.
|
|
285
|
+
Executes the code associated with the button.
|
|
286
|
+
:param button:
|
|
287
|
+
:param interaction:
|
|
288
|
+
:param data:
|
|
289
|
+
:return:
|
|
290
|
+
"""
|
|
291
|
+
code = data.pop('code', None)
|
|
292
|
+
interpreter: "DshellInterpreteur" = data.pop('interpreter', None)
|
|
293
|
+
if code is not None:
|
|
294
|
+
message = interaction
|
|
295
|
+
local_env = {
|
|
296
|
+
'__ret__': None, # environment variables, '__ret__' is used to store the return value of commands
|
|
297
|
+
'__loop__': None, # used to store the current loop variable in loop nodes if the loop identifier is not specified
|
|
298
|
+
'__break__': BoolNode(0), # used to break a loop
|
|
299
|
+
|
|
300
|
+
'__author__': IntNode(message.user.id),
|
|
301
|
+
'__author_name__': StrNode(message.user.name),
|
|
302
|
+
'__author_display_name__': StrNode(message.user.display_name),
|
|
303
|
+
'__author_avatar__': StrNode(message.user.display_avatar.url) if message.user.display_avatar else None,
|
|
304
|
+
'__author_discriminator__': StrNode(message.user.discriminator),
|
|
305
|
+
'__author_bot__': BoolNode(message.user.bot),
|
|
306
|
+
'__author_nick__': StrNode(message.user.nick) if hasattr(message.user, 'nick') else None,
|
|
307
|
+
'__author_id__': IntNode(message.user.id),
|
|
308
|
+
'__author_add_reaction__': None, # Can be overwritten by add vars_env parameter to get the author on message add event reaction
|
|
309
|
+
'__author_remove_reaction__': None, # Can be overwritten by add vars_env parameter to get the author on message remove event reaction
|
|
310
|
+
|
|
311
|
+
'__message__': StrNode(message.message.content),
|
|
312
|
+
'__message_content__': StrNode(message.message.content),
|
|
313
|
+
'__message_id__': IntNode(message.message.id),
|
|
314
|
+
'__message_author__': IntNode(message.message.author.id),
|
|
315
|
+
'__message_before__': StrNode(message.message.content), # same as __message__, but before edit. Can be overwritten by add vars_env parameter
|
|
316
|
+
'__message_created_at__': StrNode(message.message.created_at),
|
|
317
|
+
'__message_edited_at__': StrNode(message.message.edited_at),
|
|
318
|
+
'__message_reactions__': ListNode([StrNode(reaction.emoji) for reaction in message.message.reactions], bypass_limit_elt=True, editable=False),
|
|
319
|
+
'__message_add_reaction__': None, # Can be overwritten by add vars_env parameter to get the reaction added on message add event reaction
|
|
320
|
+
'__message_remove_reaction__': None, # Can be overwritten by add vars_env parameter to get the reaction removed on message remove event reaction
|
|
321
|
+
'__message_url__': StrNode(message.message.jump_url) if hasattr(message.message, 'jump_url') else None,
|
|
322
|
+
'__last_message__': IntNode(message.message.channel.last_message_id),
|
|
323
|
+
|
|
324
|
+
'__channel__': IntNode(message.message.channel.id),
|
|
325
|
+
'__channel_name__': StrNode(message.message.channel.name),
|
|
326
|
+
'__channel_type__': StrNode(message.message.channel.type.name) if hasattr(message.message.channel, 'type') else None,
|
|
327
|
+
'__channel_id__': IntNode(message.message.channel.id),
|
|
328
|
+
'__private_channel__': BoolNode(isinstance(message.message.channel, PrivateChannel)),
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if message.guild is not None:
|
|
332
|
+
local_env.update(
|
|
333
|
+
{
|
|
334
|
+
'__guild__': IntNode(message.channel.guild.id),
|
|
335
|
+
'__guild_name__': StrNode(message.channel.guild.name),
|
|
336
|
+
'__guild_id__': IntNode(message.channel.guild.id),
|
|
337
|
+
'__guild_members__': ListNode([IntNode(member.id) for member in message.channel.guild.members], bypass_limit_elt=True, editable=False),
|
|
338
|
+
'__guild_member_count__': IntNode(message.channel.guild.member_count),
|
|
339
|
+
'__guild_icon__': StrNode(message.channel.guild.icon.url) if message.channel.guild.icon else None,
|
|
340
|
+
'__guild_owner_id__': IntNode(message.channel.guild.owner_id),
|
|
341
|
+
'__guild_description__': StrNode(message.channel.guild.description),
|
|
342
|
+
'__guild_roles__': ListNode([IntNode(role.id) for role in message.channel.guild.roles], bypass_limit_elt=True, editable=False),
|
|
343
|
+
'__guild_roles_count__': IntNode(len(message.channel.guild.roles)),
|
|
344
|
+
'__guild_emojis__': ListNode([IntNode(emoji.id) for emoji in message.channel.guild.emojis], bypass_limit_elt=True, editable=False),
|
|
345
|
+
'__guild_emojis_count__': IntNode(len(message.channel.guild.emojis)),
|
|
346
|
+
'__guild_channels__': ListNode([IntNode(channel.id) for channel in message.channel.guild.channels], bypass_limit_elt=True, editable=False),
|
|
347
|
+
'__guild_text_channels__': ListNode([IntNode(channel.id) for channel in message.channel.guild.text_channels], bypass_limit_elt=True, editable=False),
|
|
348
|
+
'__guild_voice_channels__': ListNode([IntNode(channel.id) for channel in message.channel.guild.voice_channels], bypass_limit_elt=True, editable=False),
|
|
349
|
+
'__guild_categories__': ListNode([IntNode(channel.id) for channel in message.channel.guild.categories], bypass_limit_elt=True, editable=False),
|
|
350
|
+
'__guild_stage_channels__': ListNode([IntNode(channel.id) for channel in message.channel.guild.stage_channels], bypass_limit_elt=True, editable=False),
|
|
351
|
+
'__guild_forum_channels__': ListNode([IntNode(channel.id) for channel in message.channel.guild.forum_channels], bypass_limit_elt=True, editable=False),
|
|
352
|
+
'__guild_channels_count__': IntNode(len(message.channel.guild.channels)),
|
|
353
|
+
}
|
|
354
|
+
)
|
|
355
|
+
else:
|
|
356
|
+
local_env.update(
|
|
357
|
+
{
|
|
358
|
+
'__guild__': None,
|
|
359
|
+
'__guild_name__': None,
|
|
360
|
+
'__guild_id__': None,
|
|
361
|
+
'__guild_members__': None,
|
|
362
|
+
'__guild_member_count__': None,
|
|
363
|
+
'__guild_icon__': None,
|
|
364
|
+
'__guild_owner_id__': None,
|
|
365
|
+
'__guild_description__': None,
|
|
366
|
+
'__guild_roles__': None,
|
|
367
|
+
'__guild_roles_count__': None,
|
|
368
|
+
'__guild_emojis__': None,
|
|
369
|
+
'__guild_emojis_count__': None,
|
|
370
|
+
'__guild_channels__': None,
|
|
371
|
+
'__guild_text_channels__': None,
|
|
372
|
+
'__guild_voice_channels__': None,
|
|
373
|
+
'__guild_categories__': None,
|
|
374
|
+
'__guild_stage_channels__': None,
|
|
375
|
+
'__guild_forum_channels__': None,
|
|
376
|
+
'__guild_channels_count__': None,
|
|
377
|
+
}
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
local_env.update(data)
|
|
381
|
+
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
382
|
+
with new_scope(interpreter, local_env):
|
|
383
|
+
await DshellInterpreteur(code, ctx=interaction, debug=False, vars_env=interpreter.env).execute()
|
|
384
|
+
else:
|
|
385
|
+
await interaction.response.defer(invisible=True)
|
|
386
|
+
|
|
387
|
+
data.update({'code': code, 'interpreter': interpreter})
|
|
388
|
+
|
|
389
|
+
async def ui_select_callback(select: ui.Select, interaction: Interaction, data: dict[str, Any]):
|
|
390
|
+
"""
|
|
391
|
+
Callback for UI select menus.
|
|
392
|
+
Executes the code associated with the select menu.
|
|
393
|
+
:param select:
|
|
394
|
+
:param interaction:
|
|
395
|
+
:param data:
|
|
396
|
+
:return:
|
|
397
|
+
"""
|
|
398
|
+
code = data.pop('code', None)
|
|
399
|
+
interpreter: "DshellInterpreteur" = data.pop('interpreter', None)
|
|
400
|
+
|
|
401
|
+
message = interaction
|
|
402
|
+
if code is not None:
|
|
403
|
+
local_env = {
|
|
404
|
+
'__values__': ListNode([IntNode(i.id) for i in select.values]) if select.values and hasattr(
|
|
405
|
+
select.values[0], 'id') else ListNode(StrNode(i) for i in select.values),
|
|
406
|
+
'__ret__': None, # environment variables, '__ret__' is used to store the return value of commands
|
|
407
|
+
'__loop__': None,
|
|
408
|
+
# used to store the current loop variable in loop nodes if the loop identifier is not specified
|
|
409
|
+
'__break__': BoolNode(0), # used to break a loop
|
|
410
|
+
|
|
411
|
+
'__author__': IntNode(message.user.id),
|
|
412
|
+
'__author_name__': StrNode(message.user.name),
|
|
413
|
+
'__author_display_name__': StrNode(message.user.display_name),
|
|
414
|
+
'__author_avatar__': StrNode(message.user.display_avatar.url) if message.user.display_avatar else None,
|
|
415
|
+
'__author_discriminator__': StrNode(message.user.discriminator),
|
|
416
|
+
'__author_bot__': BoolNode(message.user.bot),
|
|
417
|
+
'__author_nick__': StrNode(message.user.nick) if hasattr(message.user, 'nick') else None,
|
|
418
|
+
'__author_id__': IntNode(message.user.id),
|
|
419
|
+
'__author_add_reaction__': None,
|
|
420
|
+
# Can be overwritten by add vars_env parameter to get the author on message add event reaction
|
|
421
|
+
'__author_remove_reaction__': None,
|
|
422
|
+
# Can be overwritten by add vars_env parameter to get the author on message remove event reaction
|
|
423
|
+
|
|
424
|
+
'__message__': StrNode(message.message.content),
|
|
425
|
+
'__message_content__': StrNode(message.message.content),
|
|
426
|
+
'__message_id__': IntNode(message.message.id),
|
|
427
|
+
'__message_author__': IntNode(message.message.author.id),
|
|
428
|
+
'__message_before__': StrNode(message.message.content),
|
|
429
|
+
# same as __message__, but before edit. Can be overwritten by add vars_env parameter
|
|
430
|
+
'__message_created_at__': StrNode(message.message.created_at),
|
|
431
|
+
'__message_edited_at__': StrNode(message.message.edited_at),
|
|
432
|
+
'__message_reactions__': ListNode([StrNode(reaction.emoji) for reaction in message.message.reactions],
|
|
433
|
+
bypass_limit_elt=True, editable=False),
|
|
434
|
+
'__message_add_reaction__': None,
|
|
435
|
+
# Can be overwritten by add vars_env parameter to get the reaction added on message add event reaction
|
|
436
|
+
'__message_remove_reaction__': None,
|
|
437
|
+
# Can be overwritten by add vars_env parameter to get the reaction removed on message remove event reaction
|
|
438
|
+
'__message_url__': StrNode(message.message.jump_url) if hasattr(message.message, 'jump_url') else None,
|
|
439
|
+
'__last_message__': IntNode(message.message.channel.last_message_id),
|
|
440
|
+
|
|
441
|
+
'__channel__': IntNode(message.message.channel.id),
|
|
442
|
+
'__channel_name__': StrNode(message.message.channel.name),
|
|
443
|
+
'__channel_type__': StrNode(message.message.channel.type.name) if hasattr(message.message.channel,
|
|
444
|
+
'type') else None,
|
|
445
|
+
'__channel_id__': IntNode(message.message.channel.id),
|
|
446
|
+
'__private_channel__': BoolNode(isinstance(message.message.channel, PrivateChannel)),
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if message.guild is not None:
|
|
450
|
+
local_env.update(
|
|
451
|
+
{
|
|
452
|
+
'__guild__': IntNode(message.channel.guild.id),
|
|
453
|
+
'__guild_name__': StrNode(message.channel.guild.name),
|
|
454
|
+
'__guild_id__': IntNode(message.channel.guild.id),
|
|
455
|
+
'__guild_members__': ListNode([IntNode(member.id) for member in message.channel.guild.members],
|
|
456
|
+
bypass_limit_elt=True, editable=False),
|
|
457
|
+
'__guild_member_count__': IntNode(message.channel.guild.member_count),
|
|
458
|
+
'__guild_icon__': StrNode(message.channel.guild.icon.url) if message.channel.guild.icon else None,
|
|
459
|
+
'__guild_owner_id__': IntNode(message.channel.guild.owner_id),
|
|
460
|
+
'__guild_description__': StrNode(message.channel.guild.description),
|
|
461
|
+
'__guild_roles__': ListNode([IntNode(role.id) for role in message.channel.guild.roles],
|
|
462
|
+
bypass_limit_elt=True, editable=False),
|
|
463
|
+
'__guild_roles_count__': IntNode(len(message.channel.guild.roles)),
|
|
464
|
+
'__guild_emojis__': ListNode([IntNode(emoji.id) for emoji in message.channel.guild.emojis],
|
|
465
|
+
bypass_limit_elt=True, editable=False),
|
|
466
|
+
'__guild_emojis_count__': IntNode(len(message.channel.guild.emojis)),
|
|
467
|
+
'__guild_channels__': ListNode([IntNode(channel.id) for channel in message.channel.guild.channels],
|
|
468
|
+
bypass_limit_elt=True, editable=False),
|
|
469
|
+
'__guild_text_channels__': ListNode(
|
|
470
|
+
[IntNode(channel.id) for channel in message.channel.guild.text_channels], bypass_limit_elt=True,
|
|
471
|
+
editable=False),
|
|
472
|
+
'__guild_voice_channels__': ListNode(
|
|
473
|
+
[IntNode(channel.id) for channel in message.channel.guild.voice_channels],
|
|
474
|
+
bypass_limit_elt=True, editable=False),
|
|
475
|
+
'__guild_categories__': ListNode(
|
|
476
|
+
[IntNode(channel.id) for channel in message.channel.guild.categories], bypass_limit_elt=True,
|
|
477
|
+
editable=False),
|
|
478
|
+
'__guild_stage_channels__': ListNode(
|
|
479
|
+
[IntNode(channel.id) for channel in message.channel.guild.stage_channels],
|
|
480
|
+
bypass_limit_elt=True, editable=False),
|
|
481
|
+
'__guild_forum_channels__': ListNode(
|
|
482
|
+
[IntNode(channel.id) for channel in message.channel.guild.forum_channels],
|
|
483
|
+
bypass_limit_elt=True, editable=False),
|
|
484
|
+
'__guild_channels_count__': IntNode(len(message.channel.guild.channels)),
|
|
485
|
+
}
|
|
486
|
+
)
|
|
487
|
+
else:
|
|
488
|
+
local_env.update(
|
|
489
|
+
{
|
|
490
|
+
'__guild__': None,
|
|
491
|
+
'__guild_name__': None,
|
|
492
|
+
'__guild_id__': None,
|
|
493
|
+
'__guild_members__': None,
|
|
494
|
+
'__guild_member_count__': None,
|
|
495
|
+
'__guild_icon__': None,
|
|
496
|
+
'__guild_owner_id__': None,
|
|
497
|
+
'__guild_description__': None,
|
|
498
|
+
'__guild_roles__': None,
|
|
499
|
+
'__guild_roles_count__': None,
|
|
500
|
+
'__guild_emojis__': None,
|
|
501
|
+
'__guild_emojis_count__': None,
|
|
502
|
+
'__guild_channels__': None,
|
|
503
|
+
'__guild_text_channels__': None,
|
|
504
|
+
'__guild_voice_channels__': None,
|
|
505
|
+
'__guild_categories__': None,
|
|
506
|
+
'__guild_stage_channels__': None,
|
|
507
|
+
'__guild_forum_channels__': None,
|
|
508
|
+
'__guild_channels_count__': None,
|
|
509
|
+
}
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
local_env.update(data)
|
|
513
|
+
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
514
|
+
with new_scope(interpreter, local_env):
|
|
515
|
+
await DshellInterpreteur(code, ctx=interaction, debug=False, vars_env=interpreter.env).execute()
|
|
516
|
+
else:
|
|
517
|
+
await interaction.response.defer(invisible=True)
|
|
518
|
+
|
|
519
|
+
data.update({'code': code, 'interpreter': interpreter})
|
|
@@ -19,7 +19,7 @@ def utils_check_embeds_arguments(_CMD: StrNode,
|
|
|
19
19
|
|
|
20
20
|
if embeds is not None:
|
|
21
21
|
if isinstance(embeds, EmbedNode):
|
|
22
|
-
final_embeds.
|
|
22
|
+
final_embeds.add(embeds)
|
|
23
23
|
elif isinstance(embeds, ListNode):
|
|
24
24
|
if (embed_list_size := len(embeds)) > 10:
|
|
25
25
|
raise Exception(f"Embeds argument has more than 10 items, not {embed_list_size} in '{_CMD}' command")
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="dshellInterpreter",
|
|
8
|
-
version="1.2.0.
|
|
8
|
+
version="1.2.0.17",
|
|
9
9
|
author="Chronos",
|
|
10
10
|
author_email="vagabonwalybi@gmail.com",
|
|
11
11
|
description="A Discord bot interpreter for creating custom commands and automations.",
|
|
@@ -1,361 +0,0 @@
|
|
|
1
|
-
from Dshell.full_import import (ButtonStyle,
|
|
2
|
-
PrivateChannel,
|
|
3
|
-
Interaction,
|
|
4
|
-
Button,
|
|
5
|
-
MISSING,
|
|
6
|
-
EasyModifiedViews,
|
|
7
|
-
CustomIDNotFound,
|
|
8
|
-
SelectMenu,
|
|
9
|
-
ComponentType,
|
|
10
|
-
Select,
|
|
11
|
-
random)
|
|
12
|
-
|
|
13
|
-
from ..DshellParser.ast_nodes import UiSelectNode, UiButtonNode, CodeNode, OptionUiSelectNode, ListNode
|
|
14
|
-
|
|
15
|
-
from ..DshellInterpreteur.utils_interpreter import regroupe_commandes
|
|
16
|
-
|
|
17
|
-
from ..DshellInterpreteur.dshell_scope import new_scope
|
|
18
|
-
|
|
19
|
-
from Dshell.full_import import Any, TYPE_CHECKING, Union
|
|
20
|
-
|
|
21
|
-
from .utils.utils_type_validation import (_validate_optional_code_node,
|
|
22
|
-
_validate_optional_int,
|
|
23
|
-
_validate_optional_string)
|
|
24
|
-
|
|
25
|
-
from .utils.utils_global import utils_refactor_emoji
|
|
26
|
-
|
|
27
|
-
if TYPE_CHECKING:
|
|
28
|
-
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
ButtonStyleValues: set = {i.name for i in ButtonStyle}
|
|
32
|
-
SelectSyleValues: dict = {'string': ComponentType.string_select,
|
|
33
|
-
'role': ComponentType.role_select,
|
|
34
|
-
'user': ComponentType.user_select,
|
|
35
|
-
'mention': ComponentType.mentionable_select,
|
|
36
|
-
'channel': ComponentType.channel_select}
|
|
37
|
-
|
|
38
|
-
async def build_ui_button_parameters(ui_button_node: UiButtonNode, interpreter: "DshellInterpreteur"):
|
|
39
|
-
"""
|
|
40
|
-
Builds the parameters for a UI component from the UiNode.
|
|
41
|
-
Can accept buttons and select menus.
|
|
42
|
-
:param ui_node:
|
|
43
|
-
:param interpreter:
|
|
44
|
-
:return:
|
|
45
|
-
"""
|
|
46
|
-
regrouped_parameters = await regroupe_commandes(ui_button_node.body, interpreter, normalise=True)
|
|
47
|
-
args_button: dict[str, list[Any]] = regrouped_parameters.get_dict_parameters()
|
|
48
|
-
|
|
49
|
-
code = args_button.pop('code', None)
|
|
50
|
-
style = args_button.pop('style', 'primary').lower()
|
|
51
|
-
custom_id = args_button.pop('custom_id', 'ui_button_'+str(random()))
|
|
52
|
-
row = args_button.pop('row', 0)
|
|
53
|
-
emoji = utils_refactor_emoji(args_button.pop('emoji', None))
|
|
54
|
-
|
|
55
|
-
_validate_optional_code_node(code, "Button code", "build_ui_button")
|
|
56
|
-
|
|
57
|
-
if not isinstance(custom_id, str):
|
|
58
|
-
raise TypeError(f"Button custom_id must be a string, not {type(custom_id)} !")
|
|
59
|
-
|
|
60
|
-
if style not in ButtonStyleValues:
|
|
61
|
-
raise ValueError(f"Button style must be one of {', '.join(ButtonStyleValues)}, not '{style}' !")
|
|
62
|
-
|
|
63
|
-
args_button['custom_id'] = custom_id
|
|
64
|
-
args_button['row'] = row
|
|
65
|
-
args_button['style'] = ButtonStyle[style]
|
|
66
|
-
args_button['emoji'] = emoji
|
|
67
|
-
args = args_button.pop('*', ())
|
|
68
|
-
yield args, args_button, code
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
async def build_ui_select_parameters(ui_select_node: UiSelectNode, interpreter: "DshellInterpreteur"):
|
|
72
|
-
"""
|
|
73
|
-
Builds the parameters for a UI select menu from the UiNode.
|
|
74
|
-
:param ui_select_node:
|
|
75
|
-
:param interpreter:
|
|
76
|
-
:return:
|
|
77
|
-
"""
|
|
78
|
-
regrouped_parameters = await regroupe_commandes(ui_select_node.body, interpreter, normalise=True)
|
|
79
|
-
args_select: dict[str, list[Any]] = regrouped_parameters.get_dict_parameters()
|
|
80
|
-
|
|
81
|
-
code = args_select.pop('code', None)
|
|
82
|
-
custom_id = args_select.pop('custom_id', 'ui_select_'+str(random()))
|
|
83
|
-
select_type = args_select.pop('type', 'string').lower()
|
|
84
|
-
|
|
85
|
-
disabled = args_select.get('disabled', False)
|
|
86
|
-
max_values = args_select.get('max', 1)
|
|
87
|
-
min_values = args_select.get('min', 1)
|
|
88
|
-
placeholder = args_select.get('placeholder', "")
|
|
89
|
-
row = args_select.pop('row', 0)
|
|
90
|
-
|
|
91
|
-
_validate_optional_code_node(code, "Select code", "build_ui_select")
|
|
92
|
-
|
|
93
|
-
if not isinstance(custom_id, str):
|
|
94
|
-
raise TypeError(f"Select custom_id must be a string, not {type(custom_id)} !")
|
|
95
|
-
|
|
96
|
-
if select_type is None or not isinstance(select_type, str) or select_type not in SelectSyleValues:
|
|
97
|
-
raise TypeError(f"Select type must be a string, not {type(select_type)} !")
|
|
98
|
-
|
|
99
|
-
if not isinstance(disabled, bool):
|
|
100
|
-
raise TypeError(f"Select disabled must be a bool, not {type(disabled)} !")
|
|
101
|
-
|
|
102
|
-
if not isinstance(max_values, int):
|
|
103
|
-
raise TypeError(f"Select max_values must be an int, not {type(max_values)} !")
|
|
104
|
-
|
|
105
|
-
if not isinstance(min_values, int):
|
|
106
|
-
raise TypeError(f"Select min_values must be an int, not {type(min_values)} !")
|
|
107
|
-
|
|
108
|
-
if not isinstance(placeholder, str):
|
|
109
|
-
raise TypeError(f"Select placeholder must be a string, not {type(placeholder)} !")
|
|
110
|
-
|
|
111
|
-
_validate_optional_int(row, "Select row", "build_ui_select")
|
|
112
|
-
|
|
113
|
-
args_select["disabled"] = disabled
|
|
114
|
-
args_select["max_values"] = max_values
|
|
115
|
-
args_select["min_values"] = min_values
|
|
116
|
-
args_select["options"] = await build_ui_select_options(ui_select_node.options, interpreter)
|
|
117
|
-
args_select["placeholder"] = placeholder
|
|
118
|
-
args_select["row"] = row
|
|
119
|
-
args_select["type"] = SelectSyleValues[select_type]
|
|
120
|
-
args_select['custom_id'] = custom_id
|
|
121
|
-
args = args_select.pop('*', ())
|
|
122
|
-
|
|
123
|
-
yield args, args_select, code
|
|
124
|
-
|
|
125
|
-
async def build_ui_select_options(option_nodes: list[OptionUiSelectNode], interpreter: "DshellInterpreteur"):
|
|
126
|
-
"""
|
|
127
|
-
Builds the options for a UI select menu from the OptionUiSelectNode.
|
|
128
|
-
:param option_nodes:
|
|
129
|
-
:param interpreter:
|
|
130
|
-
:return:
|
|
131
|
-
"""
|
|
132
|
-
option_results: list[dict[str, Any]] = []
|
|
133
|
-
|
|
134
|
-
for option_node in option_nodes:
|
|
135
|
-
regrouped_parameters = await regroupe_commandes(option_node.body, interpreter, normalise=True)
|
|
136
|
-
args_option: dict[str, list[Any]] = regrouped_parameters.get_dict_parameters()
|
|
137
|
-
|
|
138
|
-
label = args_option.pop('label', None)
|
|
139
|
-
value = args_option.pop('value', MISSING)
|
|
140
|
-
description = args_option.pop('description', None)
|
|
141
|
-
emoji = utils_refactor_emoji(args_option.pop('emoji', None))
|
|
142
|
-
default = args_option.pop('default', False)
|
|
143
|
-
|
|
144
|
-
if label is None or not isinstance(label, str):
|
|
145
|
-
raise TypeError(f"Option label must be a string, not {type(label)} !")
|
|
146
|
-
|
|
147
|
-
if len(label) > 100:
|
|
148
|
-
raise ValueError("Option label must be less than 100 characters !")
|
|
149
|
-
|
|
150
|
-
if value and not isinstance(value, str):
|
|
151
|
-
raise TypeError(f"Option value must be a string, not {type(value)} !")
|
|
152
|
-
|
|
153
|
-
if value and len(value) > 100:
|
|
154
|
-
raise ValueError("Option value must be less than 100 characters !")
|
|
155
|
-
|
|
156
|
-
_validate_optional_string(description, "Option description", "build_ui_option")
|
|
157
|
-
|
|
158
|
-
if description is not None and len(description) > 100:
|
|
159
|
-
raise ValueError("Option description must be less than 100 characters !")
|
|
160
|
-
|
|
161
|
-
_validate_optional_string(emoji, "Option emoji", "build_ui_option")
|
|
162
|
-
|
|
163
|
-
if not isinstance(default, bool):
|
|
164
|
-
raise TypeError(f"Option default must be a bool, not {type(default)} !")
|
|
165
|
-
|
|
166
|
-
option_dict = {
|
|
167
|
-
'label': label,
|
|
168
|
-
'value': value,
|
|
169
|
-
'description': description,
|
|
170
|
-
'emoji': emoji,
|
|
171
|
-
'default': default,
|
|
172
|
-
}
|
|
173
|
-
option_results.append(option_dict)
|
|
174
|
-
|
|
175
|
-
return option_results
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
async def build_ui(ui_node: Union[UiButtonNode, UiSelectNode], interpreter: "DshellInterpreteur") -> EasyModifiedViews:
|
|
179
|
-
"""
|
|
180
|
-
Builds a UI component from the UiNode.
|
|
181
|
-
Can accept buttons and select menus.
|
|
182
|
-
:param ui_node:
|
|
183
|
-
:param interpreter:
|
|
184
|
-
:return:
|
|
185
|
-
"""
|
|
186
|
-
view = EasyModifiedViews()
|
|
187
|
-
|
|
188
|
-
if isinstance(ui_node, UiButtonNode):
|
|
189
|
-
async for _, args_button, code in build_ui_button_parameters(ui_node, interpreter):
|
|
190
|
-
b = Button(**args_button)
|
|
191
|
-
view.add_items(b)
|
|
192
|
-
view.set_callable(b.custom_id, _callable=ui_button_callback, data={'code': code, 'interpreter': interpreter})
|
|
193
|
-
|
|
194
|
-
elif isinstance(ui_node, UiSelectNode):
|
|
195
|
-
s = SelectMenu()
|
|
196
|
-
async for _, args_select, code in build_ui_select_parameters(ui_node, interpreter):
|
|
197
|
-
|
|
198
|
-
options = args_select.pop("options", [])
|
|
199
|
-
select_type = args_select.pop("type")
|
|
200
|
-
|
|
201
|
-
if select_type == ComponentType.string_select:
|
|
202
|
-
menu = s.add_string_select_menu(**args_select)
|
|
203
|
-
|
|
204
|
-
for option in options:
|
|
205
|
-
menu.add_option(**option)
|
|
206
|
-
|
|
207
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
208
|
-
|
|
209
|
-
elif select_type == ComponentType.role_select:
|
|
210
|
-
s.add_role_select_menu(**args_select)
|
|
211
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
212
|
-
|
|
213
|
-
elif select_type == ComponentType.user_select:
|
|
214
|
-
s.add_user_select_menu(**args_select)
|
|
215
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
216
|
-
|
|
217
|
-
elif select_type == ComponentType.mentionable_select:
|
|
218
|
-
s.add_mentionable_select_menu(**args_select)
|
|
219
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
220
|
-
|
|
221
|
-
elif select_type == ComponentType.channel_select:
|
|
222
|
-
s.add_channel_select_menu(**args_select)
|
|
223
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, 'interpreter': interpreter})
|
|
224
|
-
|
|
225
|
-
view.add_items(s)
|
|
226
|
-
|
|
227
|
-
else:
|
|
228
|
-
raise TypeError(f"UI node must be UiButtonNode or UiSelectNode, not {type(ui_node)} !")
|
|
229
|
-
|
|
230
|
-
return view
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
async def rebuild_ui(ui_node: Union[UiButtonNode, UiSelectNode], view: EasyModifiedViews, interpreter: "DshellInterpreteur") -> EasyModifiedViews:
|
|
235
|
-
"""
|
|
236
|
-
Rebuilds a UI component from an existing EasyModifiedViews.
|
|
237
|
-
:param view:
|
|
238
|
-
:param interpreter:
|
|
239
|
-
:return:
|
|
240
|
-
"""
|
|
241
|
-
if isinstance(ui_node, UiButtonNode):
|
|
242
|
-
|
|
243
|
-
async for args, args_button, code in build_ui_button_parameters(ui_node, interpreter):
|
|
244
|
-
try:
|
|
245
|
-
ui: Button = view.get_ui(args_button['custom_id'])
|
|
246
|
-
except CustomIDNotFound:
|
|
247
|
-
raise ValueError(f"Button with custom_id '{args_button['custom_id']}' not found in the view !")
|
|
248
|
-
|
|
249
|
-
ui.label = args_button.get('label', ui.label)
|
|
250
|
-
ui.style = args_button.get('style', ui.style)
|
|
251
|
-
ui.emoji = args_button.get('emoji', ui.emoji)
|
|
252
|
-
ui.disabled = args_button.get('disabled', ui.disabled)
|
|
253
|
-
ui.url = args_button.get('url', ui.url)
|
|
254
|
-
ui.row = args_button.get('row', ui.row)
|
|
255
|
-
new_code = code if code is not None else view.get_callable_data(args_button['custom_id'])['code']
|
|
256
|
-
view.set_callable(args_button['custom_id'], _callable=ui_button_callback, data={'code': new_code, 'interpreter': interpreter})
|
|
257
|
-
|
|
258
|
-
elif isinstance(ui_node, UiSelectNode):
|
|
259
|
-
|
|
260
|
-
async for args, args_select, code in build_ui_select_parameters(ui_select_node=ui_node, interpreter=interpreter):
|
|
261
|
-
try:
|
|
262
|
-
ui: Select = view.get_ui(args_select['custom_id'])
|
|
263
|
-
except CustomIDNotFound:
|
|
264
|
-
raise ValueError(f"Select menu with custom_id '{args_select['custom_id']}' not found in the view !")
|
|
265
|
-
|
|
266
|
-
ui.placeholder = args_select.get('placeholder', ui.placeholder)
|
|
267
|
-
ui.min_values = args_select.get('min_values', ui.min_values)
|
|
268
|
-
ui.max_values = args_select.get('max_values', ui.max_values)
|
|
269
|
-
ui.disabled = args_select.get('disabled', ui.disabled)
|
|
270
|
-
|
|
271
|
-
ui.options.clear()
|
|
272
|
-
options = args_select.pop("options", [])
|
|
273
|
-
for option in options:
|
|
274
|
-
ui.add_option(**option)
|
|
275
|
-
|
|
276
|
-
new_code = code if code is not None else view.get_callable_data(args_select['custom_id'])['code']
|
|
277
|
-
view.set_callable(args_select['custom_id'], _callable=ui_select_callback, data={'code': new_code, 'interpreter': interpreter})
|
|
278
|
-
|
|
279
|
-
return view
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
async def ui_button_callback(button: Button, interaction: Interaction, data: dict[str, Any]):
|
|
283
|
-
"""
|
|
284
|
-
Callback for UI buttons.
|
|
285
|
-
Executes the code associated with the button.
|
|
286
|
-
:param button:
|
|
287
|
-
:param interaction:
|
|
288
|
-
:param data:
|
|
289
|
-
:return:
|
|
290
|
-
"""
|
|
291
|
-
code = data.pop('code', None)
|
|
292
|
-
interpreter: "DshellInterpreteur" = data.pop('interpreter', None)
|
|
293
|
-
if code is not None:
|
|
294
|
-
local_env = {
|
|
295
|
-
'__ret__': None,
|
|
296
|
-
'__guild__': interaction.guild.name if interaction.guild else None,
|
|
297
|
-
'__channel__': interaction.channel.name if interaction.channel else None,
|
|
298
|
-
'__author__': interaction.user.id,
|
|
299
|
-
'__author_name__': interaction.user.name,
|
|
300
|
-
'__author_display_name__': interaction.user.display_name,
|
|
301
|
-
'__author_avatar__': interaction.user.display_avatar.url if interaction.user.display_avatar else None,
|
|
302
|
-
'__author_discriminator__': interaction.user.discriminator,
|
|
303
|
-
'__author_bot__': interaction.user.bot,
|
|
304
|
-
'__author_nick__': interaction.user.nick if hasattr(interaction.user, 'nick') else None,
|
|
305
|
-
'__author_id__': interaction.user.id,
|
|
306
|
-
'__message__': interaction.message.content if hasattr(interaction.message, 'content') else None,
|
|
307
|
-
'__message_id__': interaction.message.id if hasattr(interaction.message, 'id') else None,
|
|
308
|
-
'__channel_name__': interaction.channel.name if interaction.channel else None,
|
|
309
|
-
'__channel_type__': interaction.channel.type.name if hasattr(interaction.channel, 'type') else None,
|
|
310
|
-
'__channel_id__': interaction.channel.id if interaction.channel else None,
|
|
311
|
-
'__private_channel__': isinstance(interaction.channel, PrivateChannel),
|
|
312
|
-
}
|
|
313
|
-
local_env.update(data)
|
|
314
|
-
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
315
|
-
with new_scope(interpreter, local_env):
|
|
316
|
-
await DshellInterpreteur(code, ctx=interaction, debug=False, vars_env=interpreter.env).execute()
|
|
317
|
-
else:
|
|
318
|
-
await interaction.response.defer(invisible=True)
|
|
319
|
-
|
|
320
|
-
data.update({'code': code, 'interpreter': interpreter})
|
|
321
|
-
|
|
322
|
-
async def ui_select_callback(select: Select, interaction: Interaction, data: dict[str, Any]):
|
|
323
|
-
"""
|
|
324
|
-
Callback for UI select menus.
|
|
325
|
-
Executes the code associated with the select menu.
|
|
326
|
-
:param select:
|
|
327
|
-
:param interaction:
|
|
328
|
-
:param data:
|
|
329
|
-
:return:
|
|
330
|
-
"""
|
|
331
|
-
code = data.pop('code', None)
|
|
332
|
-
interpreter: "DshellInterpreteur" = data.pop('interpreter', None)
|
|
333
|
-
if code is not None:
|
|
334
|
-
local_env = {
|
|
335
|
-
'__ret__': None,
|
|
336
|
-
'__guild__': interaction.guild.name if interaction.guild else None,
|
|
337
|
-
'__channel__': interaction.channel.name if interaction.channel else None,
|
|
338
|
-
'__author__': interaction.user.id,
|
|
339
|
-
'__author_name__': interaction.user.name,
|
|
340
|
-
'__author_display_name__': interaction.user.display_name,
|
|
341
|
-
'__author_avatar__': interaction.user.display_avatar.url if interaction.user.display_avatar else None,
|
|
342
|
-
'__author_discriminator__': interaction.user.discriminator,
|
|
343
|
-
'__author_bot__': interaction.user.bot,
|
|
344
|
-
'__author_nick__': interaction.user.nick if hasattr(interaction.user, 'nick') else None,
|
|
345
|
-
'__author_id__': interaction.user.id,
|
|
346
|
-
'__message__': interaction.message.content if hasattr(interaction.message, 'content') else None,
|
|
347
|
-
'__message_id__': interaction.message.id if hasattr(interaction.message, 'id') else None,
|
|
348
|
-
'__channel_name__': interaction.channel.name if interaction.channel else None,
|
|
349
|
-
'__channel_type__': interaction.channel.type.name if hasattr(interaction.channel, 'type') else None,
|
|
350
|
-
'__channel_id__': interaction.channel.id if interaction.channel else None,
|
|
351
|
-
'__private_channel__': isinstance(interaction.channel, PrivateChannel),
|
|
352
|
-
'__values__': ListNode([i.id for i in select.values]) if select.values and hasattr(select.values[0], 'id') else ListNode(select.values)
|
|
353
|
-
}
|
|
354
|
-
local_env.update(data)
|
|
355
|
-
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
356
|
-
with new_scope(interpreter, local_env):
|
|
357
|
-
await DshellInterpreteur(code, ctx=interaction, debug=False, vars_env=interpreter.env).execute()
|
|
358
|
-
else:
|
|
359
|
-
await interaction.response.defer(invisible=True)
|
|
360
|
-
|
|
361
|
-
data.update({'code': code, 'interpreter': interpreter})
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/__init__.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_channel.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_embed.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_file.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_member.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_message.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/dshell_role.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DISCORD_COMMANDS/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/dshell_scope.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellInterpreteur/errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellParser/dshell_parser.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellPreProcess/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellTokenizer/__init__.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellTokenizer/dshell_keywords.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/Dshell/DshellTokenizer/dshell_tokenizer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/dshellInterpreter.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/dshellInterpreter.egg-info/requires.txt
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.0.15 → dshellinterpreter-1.2.0.17}/dshellInterpreter.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|