dshellInterpreter 0.1.13__tar.gz → 0.1.15__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 (24) hide show
  1. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/DISCORD_COMMANDS/dshell_channel.py +55 -2
  2. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/DISCORD_COMMANDS/dshell_member.py +41 -3
  3. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/DISCORD_COMMANDS/dshell_message.py +32 -3
  4. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/_DshellInterpreteur/dshell_interpreter.py +8 -4
  5. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/_DshellParser/ast_nodes.py +160 -0
  6. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/_DshellParser/dshell_parser.py +20 -1
  7. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/_DshellTokenizer/dshell_keywords.py +13 -1
  8. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/_DshellTokenizer/dshell_token_type.py +14 -0
  9. {dshellinterpreter-0.1.13/dshellInterpreter.egg-info → dshellinterpreter-0.1.15}/PKG-INFO +1 -1
  10. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15/dshellInterpreter.egg-info}/PKG-INFO +1 -1
  11. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/setup.py +1 -1
  12. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/DISCORD_COMMANDS/__init__.py +0 -0
  13. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/_DshellInterpreteur/__init__.py +0 -0
  14. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/_DshellParser/__init__.py +0 -0
  15. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/_DshellTokenizer/__init__.py +0 -0
  16. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/_DshellTokenizer/dshell_tokenizer.py +0 -0
  17. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/Dshell/__init__.py +0 -0
  18. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/LICENSE +0 -0
  19. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/README.md +0 -0
  20. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/dshellInterpreter.egg-info/SOURCES.txt +0 -0
  21. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/dshellInterpreter.egg-info/dependency_links.txt +0 -0
  22. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/dshellInterpreter.egg-info/requires.txt +0 -0
  23. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/dshellInterpreter.egg-info/top_level.txt +0 -0
  24. {dshellinterpreter-0.1.13 → dshellinterpreter-0.1.15}/setup.cfg +0 -0
@@ -8,7 +8,9 @@ __all__ = [
8
8
  'dshell_create_text_channel',
9
9
  'dshell_delete_channel',
10
10
  'dshell_delete_channels',
11
- 'dshell_create_voice_channel'
11
+ 'dshell_create_voice_channel',
12
+ 'dshell_edit_text_channel',
13
+ 'dshell_edit_voice_channel'
12
14
  ]
13
15
 
14
16
 
@@ -69,7 +71,7 @@ async def dshell_delete_channel(ctx: Message, channel=None, reason=None, timeout
69
71
  channel_to_delete = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
70
72
 
71
73
  if channel_to_delete is None:
72
- raise Exception(f"Le channel {channel} n'existe pas !")
74
+ raise Exception(f"Channel {channel} not found !")
73
75
 
74
76
  await sleep(timeout)
75
77
 
@@ -90,3 +92,54 @@ async def dshell_delete_channels(ctx: Message, name=None, regex=None, reason=Non
90
92
 
91
93
  elif regex is not None and search(regex, channel.name):
92
94
  await channel.delete(reason=reason)
95
+
96
+ async def dshell_edit_text_channel(ctx: Message,
97
+ channel=None,
98
+ name=None,
99
+ position=MISSING,
100
+ slowmode=MISSING,
101
+ topic=MISSING, nsfw=MISSING,
102
+ permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
103
+ reason=None):
104
+ """
105
+ Edits a text channel on the server
106
+ """
107
+
108
+ channel_to_edit = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
109
+
110
+ if channel_to_edit is None:
111
+ raise Exception(f"Channel {channel} not found !")
112
+
113
+ await channel_to_edit.edit(name=name,
114
+ position=position,
115
+ slowmode_delay=slowmode,
116
+ topic=topic,
117
+ nsfw=nsfw,
118
+ overwrites=permission,
119
+ reason=reason)
120
+
121
+ return channel_to_edit.id
122
+
123
+ async def dshell_edit_voice_channel(ctx: Message,
124
+ channel=None,
125
+ name=None,
126
+ position=MISSING,
127
+ bitrate=MISSING,
128
+ permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
129
+ reason=None):
130
+ """
131
+ Edits a voice channel on the server
132
+ """
133
+
134
+ channel_to_edit = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
135
+
136
+ if channel_to_edit is None:
137
+ raise Exception(f"Channel {channel} not found !")
138
+
139
+ await channel_to_edit.edit(name=name,
140
+ position=position,
141
+ bitrate=bitrate,
142
+ overwrites=permission,
143
+ reason=reason)
144
+
145
+ return channel_to_edit.id
@@ -1,11 +1,13 @@
1
- from discord import MISSING, Message
1
+ from discord import MISSING, Message, Member
2
2
 
3
3
 
4
4
  __all__ = [
5
5
  "dshell_ban_member",
6
6
  "dshell_unban_member",
7
7
  "dshell_kick_member",
8
- "dshell_rename_member"
8
+ "dshell_rename_member",
9
+ "dshell_add_roles",
10
+ "dshell_remove_roles",
9
11
  ]
10
12
 
11
13
  async def dshell_ban_member(ctx: Message, member: int, reason: str = MISSING):
@@ -64,4 +66,40 @@ async def dshell_rename_member(ctx: Message, new_name, member=None):
64
66
 
65
67
  await renamed_member.edit(nick=new_name)
66
68
 
67
- return renamed_member.id
69
+ return renamed_member.id
70
+
71
+ async def dshell_add_roles(ctx: Message, roles: list[int], member=None, reason: str = None):
72
+ """
73
+ Adds roles to a member in the server.
74
+ """
75
+ target_member: Member = ctx.author if member is None else ctx.channel.guild.get_member(member)
76
+
77
+ if not target_member:
78
+ return 1 # Member not found in the server
79
+
80
+ roles_to_add = [ctx.channel.guild.get_role(role_id) for role_id in roles if ctx.channel.guild.get_role(role_id)]
81
+
82
+ if not roles_to_add:
83
+ return 2 # No valid roles found
84
+
85
+ await target_member.add_roles(*roles_to_add, reason=reason)
86
+
87
+ return target_member.id
88
+
89
+ async def dshell_remove_roles(ctx: Message, roles: list[int], member=None, reason: str = None):
90
+ """
91
+ Removes roles from a member in the server.
92
+ """
93
+ target_member: Member = ctx.author if member is None else ctx.channel.guild.get_member(member)
94
+
95
+ if not target_member:
96
+ return 1 # Member not found in the server
97
+
98
+ roles_to_remove = [ctx.channel.guild.get_role(role_id) for role_id in roles if ctx.channel.guild.get_role(role_id)]
99
+
100
+ if not roles_to_remove:
101
+ return 2 # No valid roles found
102
+
103
+ await target_member.remove_roles(*roles_to_remove, reason=reason)
104
+
105
+ return target_member.id
@@ -9,7 +9,9 @@ __all__ = [
9
9
  'dshell_purge_message',
10
10
  'dshell_edit_message',
11
11
  'dshell_research_regex_message',
12
- 'dshell_research_regex_in_content'
12
+ 'dshell_research_regex_in_content',
13
+ 'dshell_add_reactions',
14
+ 'dshell_remove_reactions'
13
15
  ]
14
16
 
15
17
 
@@ -110,7 +112,34 @@ async def dshell_research_regex_in_content(ctx: Message, regex, content):
110
112
  """
111
113
 
112
114
  if not search(regex, content):
113
- return True
115
+ return False
114
116
 
115
- return False
117
+ return True
116
118
 
119
+ async def dshell_add_reactions(ctx: Message, reactions, message=None):
120
+ """
121
+ Adds reactions to a message
122
+ """
123
+ message = ctx if message is None else ctx.channel.get_partial_message(message) # builds a reference to the message (even if it doesn't exist)
124
+
125
+ if isinstance(reactions, str):
126
+ reactions = [reactions]
127
+
128
+ for reaction in reactions:
129
+ await message.add_reaction(reaction)
130
+
131
+ return message.id
132
+
133
+ async def dshell_remove_reactions(ctx: Message, reactions, message=None):
134
+ """
135
+ Removes reactions from a message
136
+ """
137
+ message = ctx if message is None else ctx.channel.get_partial_message(message) # builds a reference to the message (even if it doesn't exist)
138
+
139
+ if isinstance(reactions, str):
140
+ reactions = [reactions]
141
+
142
+ for reaction in reactions:
143
+ await message.clear_reaction(reaction)
144
+
145
+ return message.id
@@ -4,7 +4,7 @@ from typing import TypeVar, Union, Any, Optional, Callable
4
4
 
5
5
 
6
6
  from discord import AutoShardedBot, Embed, Colour, PermissionOverwrite, Permissions, Guild, Member, Role, Message
7
- from discord.abc import GuildChannel, PrivateChannel
7
+ from discord.abc import PrivateChannel
8
8
 
9
9
  from .._DshellParser.ast_nodes import *
10
10
  from .._DshellParser.dshell_parser import parse
@@ -24,16 +24,20 @@ class DshellInterpreteur:
24
24
  Make what you want with Dshell code to interact with Discord !
25
25
  """
26
26
 
27
- def __init__(self, code: str, ctx: context, debug: bool = False):
27
+ def __init__(self, code: str, ctx: context, debug: bool = False, vars: Optional[dict[str, Any]] = None):
28
28
  """
29
29
  Interpreter Dshell code
30
30
  :param code: The code to interpret. Each line must end with a newline character, except SEPARATOR and SUB_SEPARATOR tokens.
31
+ :param ctx: The context in which the code is executed. It can be a Discord bot, a message, or a channel.
32
+ :param debug: If True, prints the AST of the code.
33
+ :param vars: Optional dictionary of variables to initialize in the interpreter's environment.
31
34
  """
32
35
  self.ast: list[ASTNode] = parse(DshellTokenizer(code).start(), StartNode([]))[0]
33
- self.env: dict[str, Any] = {}
36
+ self.env: dict[str, Any] = vars or {}
34
37
  self.ctx: context = ctx
35
38
  if debug:
36
39
  print_ast(self.ast)
40
+ self.env['__ret__'] = None
37
41
 
38
42
  async def execute(self, ast: Optional[list[All_nodes]] = None):
39
43
  """
@@ -57,7 +61,7 @@ class DshellInterpreteur:
57
61
  await self.execute(node.body)
58
62
 
59
63
  if isinstance(node, CommandNode):
60
- self.env['__cr__'] = await call_function(dshell_commands[node.name], node.body, self)
64
+ self.env['__ret__'] = await call_function(dshell_commands[node.name], node.body, self)
61
65
 
62
66
  elif isinstance(node, IfNode):
63
67
  elif_valid = False
@@ -1,4 +1,5 @@
1
1
  from typing import Optional, Any
2
+ from random import randint
2
3
 
3
4
  from .._DshellTokenizer.dshell_token_type import Token
4
5
 
@@ -39,6 +40,16 @@ class StartNode(ASTNode):
39
40
  def __repr__(self):
40
41
  return f"<Command> - {self.body}"
41
42
 
43
+ def to_dict(self):
44
+ """
45
+ Convert the StartNode to a dictionary representation.
46
+ :return: Dictionary representation of the StartNode.
47
+ """
48
+ return {
49
+ "type": "StartNode",
50
+ "body": [token.to_dict() for token in self.body]
51
+ }
52
+
42
53
 
43
54
  class ElseNode(ASTNode):
44
55
  """
@@ -53,6 +64,16 @@ class ElseNode(ASTNode):
53
64
  def __repr__(self):
54
65
  return f"<Else> - {self.body}"
55
66
 
67
+ def to_dict(self):
68
+ """
69
+ Convert the ElseNode to a dictionary representation.
70
+ :return: Dictionary representation of the ElseNode.
71
+ """
72
+ return {
73
+ "type": "ElseNode",
74
+ "body": [token.to_dict() for token in self.body]
75
+ }
76
+
56
77
 
57
78
  class ElifNode(ASTNode):
58
79
  """
@@ -71,6 +92,18 @@ class ElifNode(ASTNode):
71
92
  def __repr__(self):
72
93
  return f"<Elif> - {self.condition} - {self.body}"
73
94
 
95
+ def to_dict(self):
96
+ """
97
+ Convert the ElifNode to a dictionary representation.
98
+ :return: Dictionary representation of the ElifNode.
99
+ """
100
+ return {
101
+ "type": "ElifNode",
102
+ "condition": [token.to_dict() for token in self.condition],
103
+ "body": [token.to_dict() for token in self.body],
104
+ "parent": self.parent.id # Assuming parent is an IfNode, we store its ID
105
+ }
106
+
74
107
 
75
108
  class IfNode(ASTNode):
76
109
  """
@@ -88,10 +121,24 @@ class IfNode(ASTNode):
88
121
  self.body = body
89
122
  self.elif_nodes = elif_nodes
90
123
  self.else_body = else_body
124
+ self.id = randint(0, 1000000) # Unique identifier for the IfNode instance
91
125
 
92
126
  def __repr__(self):
93
127
  return f"<If> - {self.condition} - {self.body} *- {self.elif_nodes} **- {self.else_body}"
94
128
 
129
+ def to_dict(self):
130
+ """
131
+ Convert the IfNode to a dictionary representation.
132
+ :return: Dictionary representation of the IfNode.
133
+ """
134
+ return {
135
+ "type": "IfNode",
136
+ "condition": [token.to_dict() for token in self.condition],
137
+ "body": [token.to_dict() for token in self.body],
138
+ "elif_nodes": [elif_node.to_dict() for elif_node in self.elif_nodes] if self.elif_nodes else None,
139
+ "else_body": self.else_body.to_dict() if self.else_body else None,
140
+ "id": self.id
141
+ }
95
142
 
96
143
  class LoopNode(ASTNode):
97
144
  """
@@ -108,6 +155,16 @@ class LoopNode(ASTNode):
108
155
  def __repr__(self):
109
156
  return f"<Loop> - {self.variable.name} -> {self.variable.body} *- {self.body}"
110
157
 
158
+ def to_dict(self):
159
+ """
160
+ Convert the LoopNode to a dictionary representation.
161
+ :return: Dictionary representation of the LoopNode.
162
+ """
163
+ return {
164
+ "type": "LoopNode",
165
+ "variable": self.variable.to_dict(),
166
+ "body": [token.to_dict() for token in self.body]
167
+ }
111
168
 
112
169
  class ArgsCommandNode(ASTNode):
113
170
  """
@@ -122,6 +179,16 @@ class ArgsCommandNode(ASTNode):
122
179
  def __repr__(self):
123
180
  return f"<Args Command> - {self.body}"
124
181
 
182
+ def to_dict(self):
183
+ """
184
+ Convert the ArgsCommandNode to a dictionary representation.
185
+ :return: Dictionary representation of the ArgsCommandNode.
186
+ """
187
+ return {
188
+ "type": "ArgsCommandNode",
189
+ "body": [token.to_dict() for token in self.body]
190
+ }
191
+
125
192
 
126
193
  class CommandNode(ASTNode):
127
194
  """
@@ -138,6 +205,17 @@ class CommandNode(ASTNode):
138
205
  def __repr__(self):
139
206
  return f"<{self.name}> - {self.body}"
140
207
 
208
+ def to_dict(self):
209
+ """
210
+ Convert the CommandNode to a dictionary representation.
211
+ :return: Dictionary representation of the CommandNode.
212
+ """
213
+ return {
214
+ "type": "CommandNode",
215
+ "name": self.name,
216
+ "body": self.body.to_dict()
217
+ }
218
+
141
219
 
142
220
  class VarNode(ASTNode):
143
221
  """
@@ -154,6 +232,17 @@ class VarNode(ASTNode):
154
232
  def __repr__(self):
155
233
  return f"<VAR> - {self.name} *- {self.body}"
156
234
 
235
+ def to_dict(self):
236
+ """
237
+ Convert the VarNode to a dictionary representation.
238
+ :return: Dictionary representation of the VarNode.
239
+ """
240
+ return {
241
+ "type": "VarNode",
242
+ "name": self.name.to_dict(),
243
+ "body": [token.to_dict() for token in self.body]
244
+ }
245
+
157
246
 
158
247
  class EndNode(ASTNode):
159
248
  """
@@ -165,6 +254,15 @@ class EndNode(ASTNode):
165
254
  def __repr__(self):
166
255
  return f"<END>"
167
256
 
257
+ def to_dict(self):
258
+ """
259
+ Convert the EndNode to a dictionary representation.
260
+ :return: Dictionary representation of the EndNode.
261
+ """
262
+ return {
263
+ "type": "EndNode"
264
+ }
265
+
168
266
 
169
267
  class FieldEmbedNode(ASTNode):
170
268
  """
@@ -179,6 +277,16 @@ class FieldEmbedNode(ASTNode):
179
277
  def __repr__(self):
180
278
  return f"<EMBED_FIELD> - {self.body}"
181
279
 
280
+ def to_dict(self):
281
+ """
282
+ Convert the FieldEmbedNode to a dictionary representation.
283
+ :return: Dictionary representation of the FieldEmbedNode.
284
+ """
285
+ return {
286
+ "type": "FieldEmbedNode",
287
+ "body": [token.to_dict() for token in self.body]
288
+ }
289
+
182
290
 
183
291
  class EmbedNode(ASTNode):
184
292
  """
@@ -195,6 +303,17 @@ class EmbedNode(ASTNode):
195
303
  def __repr__(self):
196
304
  return f"<EMBED> - {self.body}"
197
305
 
306
+ def to_dict(self):
307
+ """
308
+ Convert the EmbedNode to a dictionary representation.
309
+ :return: Dictionary representation of the EmbedNode.
310
+ """
311
+ return {
312
+ "type": "EmbedNode",
313
+ "body": [token.to_dict() for token in self.body],
314
+ "fields": [field.to_dict() for field in self.fields]
315
+ }
316
+
198
317
 
199
318
  class PermissionNode(ASTNode):
200
319
  """
@@ -209,6 +328,16 @@ class PermissionNode(ASTNode):
209
328
  def __repr__(self):
210
329
  return f"<PERMISSION> - {self.body}"
211
330
 
331
+ def to_dict(self):
332
+ """
333
+ Convert the PermissionNode to a dictionary representation.
334
+ :return: Dictionary representation of the PermissionNode.
335
+ """
336
+ return {
337
+ "type": "PermissionNode",
338
+ "body": [token.to_dict() for token in self.body]
339
+ }
340
+
212
341
 
213
342
  class SleepNode(ASTNode):
214
343
  """
@@ -223,6 +352,16 @@ class SleepNode(ASTNode):
223
352
  def __repr__(self):
224
353
  return f"<SLEEP> - {self.body}"
225
354
 
355
+ def to_dict(self):
356
+ """
357
+ Convert the SleepNode to a dictionary representation.
358
+ :return: Dictionary representation of the SleepNode.
359
+ """
360
+ return {
361
+ "type": "SleepNode",
362
+ "body": [token.to_dict() for token in self.body]
363
+ }
364
+
226
365
 
227
366
  class IdentOperationNode(ASTNode):
228
367
  """
@@ -244,6 +383,17 @@ class IdentOperationNode(ASTNode):
244
383
  def __repr__(self):
245
384
  return f"<IDENT OPERATION> - {self.ident}.{self.function}({self.args})"
246
385
 
386
+ def to_dict(self):
387
+ """
388
+ Convert the IdentOperationNode to a dictionary representation.
389
+ :return: Dictionary representation of the IdentOperationNode.
390
+ """
391
+ return {
392
+ "type": "IdentOperationNode",
393
+ "ident": self.ident.to_dict(),
394
+ "function": self.function.to_dict(),
395
+ "args": self.args.to_dict()
396
+ }
247
397
 
248
398
  class ListNode(ASTNode):
249
399
  """
@@ -260,6 +410,16 @@ class ListNode(ASTNode):
260
410
  self.len_iterable: int = len(body)
261
411
  self.iterateur_count: int = 0
262
412
 
413
+ def to_dict(self):
414
+ """
415
+ Convert the ListNode to a dictionary representation.
416
+ :return: Dictionary representation of the ListNode.
417
+ """
418
+ return {
419
+ "type": "ListNode",
420
+ "body": [token.to_dict() for token in self.iterable]
421
+ }
422
+
263
423
  def add(self, value: Any):
264
424
  """
265
425
  Add a value to the list.
@@ -3,7 +3,8 @@ __all__ = [
3
3
  "parser_inline",
4
4
  "to_postfix",
5
5
  "parse_postfix_expression",
6
- "print_ast"
6
+ "print_ast",
7
+ "ast_to_dict",
7
8
  ]
8
9
 
9
10
  from typing import Union, TYPE_CHECKING
@@ -200,6 +201,24 @@ elif first_token_line.type == DTT.LIST: # si le token est une liste (qui comport
200
201
  last_block.body.append(list_node)
201
202
  """
202
203
 
204
+ def ast_to_dict(obj):
205
+ if isinstance(obj, list):
206
+ return [ast_to_dict(item) for item in obj]
207
+ elif hasattr(obj, "to_dict"):
208
+ return obj.to_dict()
209
+ else:
210
+ return obj # fallback for primitives or tokens
211
+
212
+ def dict_to_ast(data):
213
+ """
214
+ Convertit un dictionnaire en une structure AST.
215
+ :param data: le dictionnaire à convertir
216
+ :return: la structure AST correspondante
217
+ """
218
+ if isinstance(data, list):
219
+ return [dict_to_ast(item) for item in data]
220
+ elif isinstance(data, dict):
221
+ pass
203
222
 
204
223
  def parser_inline(tokens: list[Token]) -> tuple[list[list[Token]], bool]:
205
224
  """
@@ -21,19 +21,31 @@ dshell_discord_keyword: set[str] = {
21
21
  'embed', '#embed', 'field', 'perm', 'permission', '#perm', '#permission'
22
22
  }
23
23
  dshell_commands: dict[str, Callable] = {
24
+
24
25
  "sm": dshell_send_message, # send message
25
26
  "dm": dshell_delete_message,
26
27
  "pm": dshell_purge_message,
28
+ "em": dshell_edit_message, # edit message
29
+
27
30
  "cc": dshell_create_text_channel, # create channel
28
31
  "cvc": dshell_create_voice_channel, # create voice channel
29
32
  "dc": dshell_delete_channel, # delete channel
30
33
  "dcs": dshell_delete_channels, # delete several channels by name or regex
34
+
31
35
  "bm": dshell_ban_member, # ban member
32
36
  "um": dshell_unban_member, # unban member
33
37
  "km": dshell_kick_member, # kick member
34
- "em": dshell_edit_message, # edit message
38
+ "rm": dshell_rename_member, # rename member
39
+
35
40
  "srm": dshell_research_regex_message, # research regex in message
36
41
  "src": dshell_research_regex_in_content, # research regex in content
42
+
43
+ "ec": dshell_edit_text_channel, # edit text channel
44
+ "evc": dshell_edit_voice_channel, # edit voice channel
45
+
46
+ "arr": dshell_add_reactions, # add reactions to a message
47
+ "rrr": dshell_remove_reactions, # remove reactions from a message
48
+
37
49
  }
38
50
 
39
51
  dshell_mathematical_operators: dict[str, tuple[Callable, int]] = {
@@ -39,3 +39,17 @@ class Token:
39
39
 
40
40
  def __repr__(self):
41
41
  return f"<{self.type.name} '{self.value}'>"
42
+
43
+ def to_dict(self):
44
+ def serialize_value(value):
45
+ if isinstance(value, list):
46
+ return [serialize_value(v) for v in value]
47
+ elif isinstance(value, Token):
48
+ return value.to_dict()
49
+ return value
50
+
51
+ return {
52
+ "type": self.type.name,
53
+ "value": serialize_value(self.value),
54
+ "position": self.position
55
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dshellInterpreter
3
- Version: 0.1.13
3
+ Version: 0.1.15
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dshellInterpreter
3
- Version: 0.1.13
3
+ Version: 0.1.15
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
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setup(
7
7
  name="dshellInterpreter",
8
- version="0.1.13",
8
+ version="0.1.15",
9
9
  author="Chronos",
10
10
  author_email="vagabonwalybi@gmail.com",
11
11
  description="A Discord bot interpreter for creating custom commands and automations.",