dshellInterpreter 0.2.12__tar.gz → 0.2.13.1__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.

Potentially problematic release.


This version of dshellInterpreter might be problematic. Click here for more details.

Files changed (30) hide show
  1. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/DISCORD_COMMANDS/dshell_channel.py +8 -8
  2. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/DISCORD_COMMANDS/dshell_message.py +11 -7
  3. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_DshellInterpreteur/dshell_interpreter.py +60 -0
  4. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_DshellParser/ast_nodes.py +83 -1
  5. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_DshellParser/dshell_parser.py +30 -0
  6. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_DshellTokenizer/dshell_keywords.py +1 -1
  7. {dshellinterpreter-0.2.12/dshellInterpreter.egg-info → dshellinterpreter-0.2.13.1}/PKG-INFO +2 -1
  8. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1/dshellInterpreter.egg-info}/PKG-INFO +2 -1
  9. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/dshellInterpreter.egg-info/requires.txt +1 -0
  10. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/setup.py +2 -2
  11. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/DISCORD_COMMANDS/__init__.py +0 -0
  12. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/DISCORD_COMMANDS/dshell_member.py +0 -0
  13. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py +0 -0
  14. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/DISCORD_COMMANDS/dshell_role.py +0 -0
  15. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/DISCORD_COMMANDS/utils/__init__.py +0 -0
  16. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/DISCORD_COMMANDS/utils/utils_message.py +0 -0
  17. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/DISCORD_COMMANDS/utils/utils_thread.py +0 -0
  18. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_DshellInterpreteur/__init__.py +0 -0
  19. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_DshellParser/__init__.py +0 -0
  20. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_DshellTokenizer/__init__.py +0 -0
  21. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_DshellTokenizer/dshell_token_type.py +0 -0
  22. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_DshellTokenizer/dshell_tokenizer.py +0 -0
  23. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/__init__.py +0 -0
  24. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/Dshell/_utils.py +0 -0
  25. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/LICENSE +0 -0
  26. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/README.md +0 -0
  27. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/dshellInterpreter.egg-info/SOURCES.txt +0 -0
  28. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/dshellInterpreter.egg-info/dependency_links.txt +0 -0
  29. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/dshellInterpreter.egg-info/top_level.txt +0 -0
  30. {dshellinterpreter-0.2.12 → dshellinterpreter-0.2.13.1}/setup.cfg +0 -0
@@ -103,7 +103,7 @@ async def dshell_create_text_channel(ctx: Message,
103
103
  slowmode=MISSING,
104
104
  topic=MISSING,
105
105
  nsfw=MISSING,
106
- permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
106
+ permissions: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
107
107
  reason=None):
108
108
  """
109
109
  Creates a text channel on the server
@@ -129,7 +129,7 @@ async def dshell_create_text_channel(ctx: Message,
129
129
  slowmode_delay=slowmode,
130
130
  topic=topic,
131
131
  nsfw=nsfw,
132
- overwrites=permission,
132
+ overwrites=permissions,
133
133
  reason=reason)
134
134
 
135
135
  return created_channel.id
@@ -140,7 +140,7 @@ async def dshell_create_voice_channel(ctx: Message,
140
140
  category=None,
141
141
  position=MISSING,
142
142
  bitrate=MISSING,
143
- permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
143
+ permissions: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
144
144
  reason=None):
145
145
  """
146
146
  Creates a voice channel on the server
@@ -157,7 +157,7 @@ async def dshell_create_voice_channel(ctx: Message,
157
157
  category=channel_category,
158
158
  position=position,
159
159
  bitrate=bitrate,
160
- overwrites=permission,
160
+ overwrites=permissions,
161
161
  reason=reason)
162
162
 
163
163
  return created_channel.id
@@ -210,7 +210,7 @@ async def dshell_edit_text_channel(ctx: Message,
210
210
  slowmode=MISSING,
211
211
  topic=MISSING,
212
212
  nsfw=MISSING,
213
- permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
213
+ permissions: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
214
214
  reason=None):
215
215
  """
216
216
  Edits a text channel on the server
@@ -238,7 +238,7 @@ async def dshell_edit_text_channel(ctx: Message,
238
238
  slowmode_delay=slowmode if slowmode is not MISSING else channel_to_edit.slowmode_delay,
239
239
  topic=topic if topic is not MISSING else channel_to_edit.topic,
240
240
  nsfw=nsfw if nsfw is not MISSING else channel_to_edit.nsfw,
241
- overwrites=permission if permission is not MISSING else channel_to_edit.overwrites,
241
+ overwrites=permissions if permissions is not MISSING else channel_to_edit.overwrites,
242
242
  reason=reason)
243
243
 
244
244
  return channel_to_edit.id
@@ -249,7 +249,7 @@ async def dshell_edit_voice_channel(ctx: Message,
249
249
  name=None,
250
250
  position=MISSING,
251
251
  bitrate=MISSING,
252
- permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
252
+ permissions: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
253
253
  reason=None):
254
254
  """
255
255
  Edits a voice channel on the server
@@ -268,7 +268,7 @@ async def dshell_edit_voice_channel(ctx: Message,
268
268
  await channel_to_edit.edit(name=name if name is not None else channel_to_edit.name,
269
269
  position=position if position is not MISSING else channel_to_edit.position,
270
270
  bitrate=bitrate if bitrate is not MISSING else channel_to_edit.bitrate,
271
- overwrites=permission if permission is not MISSING else channel_to_edit.overwrites,
271
+ overwrites=permissions if permissions is not MISSING else channel_to_edit.overwrites,
272
272
  reason=reason)
273
273
 
274
274
  return channel_to_edit.id
@@ -4,7 +4,10 @@ from discord import Embed, Message
4
4
  from discord.ext import commands
5
5
  from discord.abc import Messageable
6
6
 
7
+ from pycordViews import EasyModifiedViews
8
+
7
9
  from .utils.utils_message import utils_get_message
10
+ from .._utils import NoneType
8
11
 
9
12
  __all__ = [
10
13
  'dshell_send_message',
@@ -21,7 +24,7 @@ __all__ = [
21
24
  ]
22
25
 
23
26
 
24
- async def dshell_send_message(ctx: Message, message=None, delete=None, channel=None, embeds=None):
27
+ async def dshell_send_message(ctx: Message, message=None, delete=None, channel=None, embeds=None, view=None) -> int:
25
28
  """
26
29
  Sends a message on Discord
27
30
  """
@@ -36,18 +39,19 @@ async def dshell_send_message(ctx: Message, message=None, delete=None, channel=N
36
39
 
37
40
  from .._DshellParser.ast_nodes import ListNode
38
41
 
39
- if embeds is None:
40
- embeds = ListNode([])
42
+ if not isinstance(embeds, (ListNode, Embed)):
43
+ raise Exception(f'Embeds must be a list of Embed objects or a single Embed object, not {type(embeds)} !')
41
44
 
42
- elif isinstance(embeds, Embed):
45
+ if isinstance(embeds, Embed):
43
46
  embeds = ListNode([embeds])
44
47
 
45
- else:
46
- raise Exception(f'Embeds must be a list of Embed objects or a single Embed object, not {type(embeds)} !')
48
+ if not isinstance(channel_to_send, (EasyModifiedViews, NoneType)):
49
+ raise Exception(f'Channel must be an UI or None, not {type(channel_to_send)} !')
47
50
 
48
51
  sended_message = await channel_to_send.send(message,
49
52
  delete_after=delete,
50
- embeds=embeds)
53
+ embeds=embeds,
54
+ view=view)
51
55
 
52
56
  return sended_message.id
53
57
 
@@ -1,9 +1,13 @@
1
1
  from asyncio import sleep
2
2
  from re import findall
3
3
  from typing import TypeVar, Union, Any, Optional, Callable
4
+ from random import choice
5
+ from string import ascii_letters, digits
4
6
  from copy import deepcopy
7
+ from pycordViews import SelectMenu, EasyModifiedViews
5
8
 
6
9
  from discord import AutoShardedBot, Embed, Colour, PermissionOverwrite, Permissions, Guild, Member, Role, Message
10
+ from discord.ui import Button
7
11
  from discord.abc import PrivateChannel
8
12
 
9
13
  from .._DshellParser.ast_nodes import *
@@ -120,6 +124,9 @@ class DshellInterpreteur:
120
124
  elif isinstance(first_node, PermissionNode):
121
125
  self.env[node.name.value] = build_permission(first_node.body, self)
122
126
 
127
+ elif isinstance(first_node, UiNode):
128
+ self.env[node.name.value] = build_ui(first_node, self)
129
+
123
130
  else:
124
131
  self.env[node.name.value] = eval_expression(node.body, self)
125
132
 
@@ -401,6 +408,59 @@ def build_colour(color: Union[int, ListNode]) -> Union[Colour, int]:
401
408
  raise TypeError(f"Color must be an integer or a ListNode, not {type(color)} !")
402
409
 
403
410
 
411
+ def build_ui(ui_node: UiNode, interpreter: DshellInterpreteur) -> EasyModifiedViews:
412
+ """
413
+ Builds a UI component from the UiNode.
414
+ Can accept buttons and select menus.
415
+ :param ui_node:
416
+ :param interpreter:
417
+ :return:
418
+ """
419
+ view = EasyModifiedViews()
420
+
421
+ for component in ui_node.buttons:
422
+ b = Button
423
+ args_button: dict[str, list[Any]] = regroupe_commandes(component.body, interpreter)[0]
424
+ args_button.pop('--*', ())
425
+ code = args_button.pop('code', None)
426
+ args = args_button.pop('*', ())
427
+ b(*args, **args_button)
428
+
429
+ custom_id = ''.join(choice(ascii_letters + digits) for _ in range(20))
430
+ b.custom_id = custom_id
431
+
432
+ view.add_items(b)
433
+ view.set_callable(custom_id, _callable=ui_button_callback, data={'code': code})
434
+
435
+ return view
436
+
437
+ async def ui_button_callback(button, interaction, data):
438
+ code = data.pop('code', None)
439
+ local_env = {}
440
+ if code is not None:
441
+ local_env = {
442
+ '__ret__': None,
443
+ '__guild__': interaction.guild.name if interaction.guild else None,
444
+ '__channel__': interaction.channel.name if interaction.channel else None,
445
+ '__author__': interaction.user.name,
446
+ '__author_display_name__': interaction.user.display_name,
447
+ '__author_avatar__': interaction.user.display_avatar.url if interaction.user.display_avatar else None,
448
+ '__author_discriminator__': interaction.user.discriminator,
449
+ '__author_bot__': interaction.user.bot,
450
+ '__author_nick__': interaction.user.nick if hasattr(interaction.user, 'nick') else None,
451
+ '__author_id__': interaction.user.id,
452
+ '__message__': interaction.message.content if hasattr(interaction.message, 'content') else None,
453
+ '__message_id__': interaction.message.id if hasattr(interaction.message, 'id') else None,
454
+ '__channel_name__': interaction.channel.name if interaction.channel else None,
455
+ '__channel_type__': interaction.channel.type.name if hasattr(interaction.channel, 'type') else None,
456
+ '__channel_id__': interaction.channel.id if interaction.channel else None,
457
+ '__private_channel__': isinstance(interaction.channel, PrivateChannel),
458
+ }
459
+ local_env.update(data)
460
+ x = DshellInterpreteur(code, interaction, debug=False)
461
+ x.env.update(local_env)
462
+ await x.execute()
463
+
404
464
  def build_permission(body: list[Token], interpreter: DshellInterpreteur) -> dict[
405
465
  Union[Member, Role], PermissionOverwrite]:
406
466
  """
@@ -20,7 +20,10 @@ __all__ = [
20
20
  'IdentOperationNode',
21
21
  'ListNode',
22
22
  'PermissionNode',
23
- 'ParamNode'
23
+ 'ParamNode',
24
+ 'UiNode',
25
+ 'UiButtonNode',
26
+ 'UiSelectNode'
24
27
  ]
25
28
 
26
29
 
@@ -439,6 +442,85 @@ class ParamNode(ASTNode):
439
442
  }
440
443
 
441
444
 
445
+ class UiButtonNode(ASTNode):
446
+ """
447
+ Node representing a UI button component in the AST.
448
+ This is used to define button elements for commands in Dshell.
449
+ """
450
+
451
+ def __init__(self, body: list[Token]):
452
+ """
453
+ :param body: list of tokens representing the button component
454
+ """
455
+ self.body = body
456
+
457
+ def __repr__(self):
458
+ return f"<UI BUTTON> - {self.body}"
459
+
460
+ def to_dict(self):
461
+ """
462
+ Convert the UiButtonNode to a dictionary representation.
463
+ :return: Dictionary representation of the UiButtonNode.
464
+ """
465
+ return {
466
+ "type": "UiButtonNode",
467
+ "body": [token.to_dict() for token in self.body]
468
+ }
469
+
470
+ class UiSelectNode(ASTNode):
471
+ """
472
+ Node representing a UI select component in the AST.
473
+ This is used to define select elements for commands in Dshell.
474
+ """
475
+
476
+ def __init__(self, body: list[Token]):
477
+ """
478
+ :param body: list of tokens representing the select component
479
+ """
480
+ self.body = body
481
+
482
+ def __repr__(self):
483
+ return f"<UI SELECT> - {self.body}"
484
+
485
+ def to_dict(self):
486
+ """
487
+ Convert the UiSelectNode to a dictionary representation.
488
+ :return: Dictionary representation of the UiSelectNode.
489
+ """
490
+ return {
491
+ "type": "UiSelectNode",
492
+ "body": [token.to_dict() for token in self.body]
493
+ }
494
+
495
+ class UiNode(ASTNode):
496
+ """
497
+ Node representing a UI component in the AST.
498
+ This is used to define UI elements for commands in Dshell.
499
+ """
500
+
501
+ def __init__(self, body, buttons: Optional[list[UiButtonNode]] = None,
502
+ selects: Optional[list[UiSelectNode]] = None):
503
+ """
504
+ :param body: list of tokens representing the UI component
505
+ """
506
+ self.body = body
507
+ self.buttons = buttons or []
508
+ self.selects = selects or []
509
+
510
+ def __repr__(self):
511
+ return f"<UI> - {self.buttons}\n\n - {self.selects}"
512
+
513
+ def to_dict(self):
514
+ """
515
+ Convert the UiNode to a dictionary representation.
516
+ :return: Dictionary representation of the UiNode.
517
+ """
518
+ return {
519
+ "type": "UiNode",
520
+ "buttons": [token.to_dict() for token in self.buttons],
521
+ "selects": [token.to_dict() for token in self.selects],
522
+ }
523
+
442
524
  class ListNode(ASTNode):
443
525
  """
444
526
  Node representing a list structure in the AST.
@@ -24,6 +24,9 @@ from .ast_nodes import (ASTNode,
24
24
  FieldEmbedNode,
25
25
  PermissionNode,
26
26
  ParamNode,
27
+ UiNode,
28
+ UiButtonNode,
29
+ UiSelectNode,
27
30
  StartNode)
28
31
  from .._DshellTokenizer import dshell_operators
29
32
  from .._DshellTokenizer.dshell_token_type import DshellTokenType as DTT
@@ -185,6 +188,33 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
185
188
  blocks.pop()
186
189
  return blocks, pointeur
187
190
 
191
+ elif first_token_line.value == 'ui':
192
+ ui_node = UiNode([])
193
+ var_node = VarNode(tokens_by_line[1], body=[ui_node])
194
+ last_block.body.append(var_node)
195
+ _, p = parse(token_lines[pointeur + 1:], ui_node)
196
+ pointeur += p + 1
197
+
198
+ elif first_token_line.value == '#ui':
199
+ if not isinstance(last_block, UiNode):
200
+ raise SyntaxError(f'[#UI] No UI open on line {first_token_line.position} !')
201
+ blocks.pop()
202
+ return blocks, pointeur
203
+
204
+ elif first_token_line.value == 'button':
205
+ if not isinstance(last_block, UiNode):
206
+ raise SyntaxError(f'[BUTTON] No UI open on line {first_token_line.position} !')
207
+ button_node = UiButtonNode(tokens_by_line[1:])
208
+ last_block.body.append(button_node)
209
+ pointeur += 1
210
+
211
+ elif first_token_line.value == 'select':
212
+ if not isinstance(last_block, UiNode):
213
+ raise SyntaxError(f'[SELECT] No UI open on line {first_token_line.position} !')
214
+ select_node = UiSelectNode(tokens_by_line[1:])
215
+ last_block.body.append(select_node)
216
+ pointeur += 1
217
+
188
218
  ############################## AUTRE ##############################
189
219
 
190
220
  elif first_token_line.type == DTT.IDENT:
@@ -21,7 +21,7 @@ dshell_keyword: set[str] = {
21
21
  }
22
22
 
23
23
  dshell_discord_keyword: set[str] = {
24
- 'embed', '#embed', 'field', 'perm', 'permission', '#perm', '#permission'
24
+ 'embed', '#embed', 'field', 'perm', 'permission', '#perm', '#permission', 'ui', '#ui', 'button', 'select'
25
25
  }
26
26
  dshell_commands: dict[str, Callable] = {
27
27
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dshellInterpreter
3
- Version: 0.2.12
3
+ Version: 0.2.13.1
4
4
  Summary: A Discord bot interpreter for creating custom commands and automations.
5
5
  Home-page: https://github.com/BOXERRMD/Dshell_Interpreter
6
6
  Author: Chronos
@@ -17,6 +17,7 @@ Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: py-cord==2.6.1
19
19
  Requires-Dist: requests
20
+ Requires-Dist: pycordviews
20
21
  Dynamic: author
21
22
  Dynamic: author-email
22
23
  Dynamic: classifier
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dshellInterpreter
3
- Version: 0.2.12
3
+ Version: 0.2.13.1
4
4
  Summary: A Discord bot interpreter for creating custom commands and automations.
5
5
  Home-page: https://github.com/BOXERRMD/Dshell_Interpreter
6
6
  Author: Chronos
@@ -17,6 +17,7 @@ Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: py-cord==2.6.1
19
19
  Requires-Dist: requests
20
+ Requires-Dist: pycordviews
20
21
  Dynamic: author
21
22
  Dynamic: author-email
22
23
  Dynamic: classifier
@@ -1,2 +1,3 @@
1
1
  py-cord==2.6.1
2
2
  requests
3
+ pycordviews
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setup(
7
7
  name="dshellInterpreter",
8
- version="0.2.12",
8
+ version="0.2.13.1",
9
9
  author="Chronos",
10
10
  author_email="vagabonwalybi@gmail.com",
11
11
  description="A Discord bot interpreter for creating custom commands and automations.",
@@ -18,7 +18,7 @@ setup(
18
18
  "Dshell._DshellParser",
19
19
  "Dshell.DISCORD_COMMANDS",
20
20
  "Dshell.DISCORD_COMMANDS.utils"],
21
- install_requires=["py-cord==2.6.1", "requests"],
21
+ install_requires=["py-cord==2.6.1", "requests", "pycordviews"],
22
22
  classifiers=[
23
23
  "Programming Language :: Python :: 3",
24
24
  "License :: OSI Approved :: MIT License",