dshellInterpreter 0.2.2__py3-none-any.whl → 0.2.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

@@ -1,3 +1,5 @@
1
1
  from .dshell_channel import *
2
2
  from .dshell_message import *
3
3
  from .dshell_member import *
4
+ from .dshell_pastbin import *
5
+ from .dshell_role import *
@@ -3,6 +3,7 @@ from re import search
3
3
  from typing import Union
4
4
 
5
5
  from discord import MISSING, PermissionOverwrite, Member, Role, Message
6
+ from discord.utils import _MissingSentinel
6
7
 
7
8
  __all__ = [
8
9
  'dshell_create_text_channel',
@@ -19,16 +20,29 @@ async def dshell_create_text_channel(ctx: Message,
19
20
  category=None,
20
21
  position=MISSING,
21
22
  slowmode=MISSING,
22
- topic=MISSING, nsfw=MISSING,
23
+ topic=MISSING,
24
+ nsfw=MISSING,
23
25
  permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
24
26
  reason=None):
25
27
  """
26
28
  Creates a text channel on the server
27
29
  """
28
30
 
29
- channel_category = ctx.channel.guild.get_channel(category)
31
+ if not isinstance(position, _MissingSentinel) and not isinstance(position, int):
32
+ raise Exception(f"Position must be an integer, not {type(position)} !")
30
33
 
31
- created_channel = await ctx.guild.create_text_channel(name,
34
+ if not isinstance(slowmode, _MissingSentinel) and not isinstance(slowmode, int):
35
+ raise Exception(f"Slowmode must be an integer, not {type(slowmode)} !")
36
+
37
+ if not isinstance(topic, _MissingSentinel) and not isinstance(topic, str):
38
+ raise Exception(f"Topic must be a string, not {type(topic)} !")
39
+
40
+ if not isinstance(nsfw, _MissingSentinel) and not isinstance(nsfw, bool):
41
+ raise Exception(f"NSFW must be a boolean, not {type(nsfw)} !")
42
+
43
+ channel_category = ctx.channel.category if category is None else ctx.channel.guild.get_channel(category)
44
+
45
+ created_channel = await ctx.guild.create_text_channel(str(name),
32
46
  category=channel_category,
33
47
  position=position,
34
48
  slowmode_delay=slowmode,
@@ -39,6 +53,7 @@ async def dshell_create_text_channel(ctx: Message,
39
53
 
40
54
  return created_channel.id
41
55
 
56
+
42
57
  async def dshell_create_voice_channel(ctx: Message,
43
58
  name,
44
59
  category=None,
@@ -49,10 +64,15 @@ async def dshell_create_voice_channel(ctx: Message,
49
64
  """
50
65
  Creates a voice channel on the server
51
66
  """
67
+ if not isinstance(position, _MissingSentinel) and not isinstance(position, int):
68
+ raise Exception(f"Position must be an integer, not {type(position)} !")
69
+
70
+ if not isinstance(bitrate, _MissingSentinel) and not isinstance(bitrate, int):
71
+ raise Exception(f"Bitrate must be an integer, not {type(bitrate)} !")
52
72
 
53
- channel_category = ctx.channel.guild.get_channel(category)
73
+ channel_category = ctx.channel.category if category is None else ctx.channel.guild.get_channel(category)
54
74
 
55
- created_channel = await ctx.guild.create_voice_channel(name,
75
+ created_channel = await ctx.guild.create_voice_channel(str(name),
56
76
  category=channel_category,
57
77
  position=position,
58
78
  bitrate=bitrate,
@@ -67,6 +87,8 @@ async def dshell_delete_channel(ctx: Message, channel=None, reason=None, timeout
67
87
  Deletes a channel.
68
88
  You can add a waiting time before it is deleted (in seconds)
69
89
  """
90
+ if not isinstance(timeout, int):
91
+ raise Exception(f'Timeout must be an integer, not {type(timeout)} !')
70
92
 
71
93
  channel_to_delete = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
72
94
 
@@ -85,6 +107,12 @@ async def dshell_delete_channels(ctx: Message, name=None, regex=None, reason=Non
85
107
  Deletes all channels with the same name and/or matching the same regex.
86
108
  If neither is set, it will delete all channels with the same name as the one where the command was executed.
87
109
  """
110
+ if name is not None and not isinstance(name, str):
111
+ raise Exception(f"Name must be a string, not {type(name)} !")
112
+
113
+ if regex is not None and not isinstance(regex, str):
114
+ raise Exception(f"Regex must be a string, not {type(regex)} !")
115
+
88
116
  for channel in ctx.channel.guild.channels:
89
117
 
90
118
  if name is not None and channel.name == str(name):
@@ -93,19 +121,32 @@ async def dshell_delete_channels(ctx: Message, name=None, regex=None, reason=Non
93
121
  elif regex is not None and search(regex, channel.name):
94
122
  await channel.delete(reason=reason)
95
123
 
124
+
96
125
  async def dshell_edit_text_channel(ctx: Message,
97
- channel=None,
98
- name=None,
99
- position=MISSING,
100
- slowmode=MISSING,
101
- topic=MISSING,
102
- nsfw=MISSING,
103
- permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
104
- reason=None):
126
+ channel=None,
127
+ name=None,
128
+ position=MISSING,
129
+ slowmode=MISSING,
130
+ topic=MISSING,
131
+ nsfw=MISSING,
132
+ permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
133
+ reason=None):
105
134
  """
106
135
  Edits a text channel on the server
107
136
  """
108
137
 
138
+ if not isinstance(position, _MissingSentinel) and not isinstance(position, int):
139
+ raise Exception(f"Position must be an integer, not {type(position)} !")
140
+
141
+ if not isinstance(slowmode, _MissingSentinel) and not isinstance(slowmode, int):
142
+ raise Exception(f"Slowmode must be an integer, not {type(slowmode)} !")
143
+
144
+ if not isinstance(topic, _MissingSentinel) and not isinstance(topic, str):
145
+ raise Exception(f"Topic must be a string, not {type(topic)} !")
146
+
147
+ if not isinstance(nsfw, _MissingSentinel) and not isinstance(nsfw, bool):
148
+ raise Exception(f"NSFW must be a boolean, not {type(nsfw)} !")
149
+
109
150
  channel_to_edit = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
110
151
 
111
152
  if channel_to_edit is None:
@@ -121,16 +162,22 @@ async def dshell_edit_text_channel(ctx: Message,
121
162
 
122
163
  return channel_to_edit.id
123
164
 
165
+
124
166
  async def dshell_edit_voice_channel(ctx: Message,
125
- channel=None,
126
- name=None,
127
- position=MISSING,
128
- bitrate=MISSING,
129
- permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
130
- reason=None):
167
+ channel=None,
168
+ name=None,
169
+ position=MISSING,
170
+ bitrate=MISSING,
171
+ permission: dict[Union[Member, Role], PermissionOverwrite] = MISSING,
172
+ reason=None):
131
173
  """
132
174
  Edits a voice channel on the server
133
175
  """
176
+ if not isinstance(position, _MissingSentinel) and not isinstance(position, int):
177
+ raise Exception(f"Position must be an integer, not {type(position)} !")
178
+
179
+ if not isinstance(bitrate, _MissingSentinel) and not isinstance(bitrate, int):
180
+ raise Exception(f"Bitrate must be an integer, not {type(bitrate)} !")
134
181
 
135
182
  channel_to_edit = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
136
183
 
@@ -1,5 +1,6 @@
1
- from discord import MISSING, Message, Member
1
+ from datetime import timedelta, datetime
2
2
 
3
+ from discord import MISSING, Message, Member, Permissions
3
4
 
4
5
  __all__ = [
5
6
  "dshell_ban_member",
@@ -8,8 +9,12 @@ __all__ = [
8
9
  "dshell_rename_member",
9
10
  "dshell_add_roles",
10
11
  "dshell_remove_roles",
12
+ "dshell_check_permissions",
13
+ "dshell_timeout_member",
14
+ "dshell_move_member"
11
15
  ]
12
16
 
17
+
13
18
  async def dshell_ban_member(ctx: Message, member: int, reason: str = MISSING):
14
19
  """
15
20
  Bans a member from the server.
@@ -17,12 +22,13 @@ async def dshell_ban_member(ctx: Message, member: int, reason: str = MISSING):
17
22
  banned_member = ctx.channel.guild.get_member(member)
18
23
 
19
24
  if not banned_member:
20
- return 1 # Member not found in the server
25
+ raise Exception(f'Member {member} not found in the server !')
21
26
 
22
27
  await ctx.channel.guild.ban(banned_member, reason=reason)
23
28
 
24
29
  return banned_member.id
25
30
 
31
+
26
32
  async def dshell_unban_member(ctx: Message, user: int, reason: str = MISSING):
27
33
  """
28
34
  Unbans a user from the server.
@@ -36,12 +42,13 @@ async def dshell_unban_member(ctx: Message, user: int, reason: str = MISSING):
36
42
  break
37
43
 
38
44
  if not user_to_unban:
39
- return 1 # User not found in the banned list
45
+ raise Exception(f'User {user} not found in the banned list')
40
46
 
41
47
  await ctx.channel.guild.unban(user_to_unban, reason=reason)
42
48
 
43
49
  return user_to_unban.id
44
50
 
51
+
45
52
  async def dshell_kick_member(ctx: Message, member: int, reason: str = MISSING):
46
53
  """
47
54
  Kicks a member from the server.
@@ -49,12 +56,33 @@ async def dshell_kick_member(ctx: Message, member: int, reason: str = MISSING):
49
56
  kicked_member = ctx.channel.guild.get_member(member)
50
57
 
51
58
  if not kicked_member:
52
- return 1 # Member not found in the server
59
+ raise Exception(f'Member {member} not found in the server !')
53
60
 
54
61
  await ctx.channel.guild.kick(kicked_member, reason=reason)
55
62
 
56
63
  return kicked_member.id
57
64
 
65
+
66
+ async def dshell_timeout_member(ctx: Message, duration: int, member=None, reason: str = MISSING):
67
+ """
68
+ Timeouts a member in the server for a specified duration.
69
+ """
70
+ target_member = ctx.author if member is None else ctx.channel.guild.get_member(member)
71
+
72
+ if not target_member:
73
+ raise Exception(f'Member {member} not found in the server !')
74
+
75
+ if not isinstance(duration, int):
76
+ raise TypeError("Duration must be an integer representing seconds.")
77
+
78
+ if duration < 0:
79
+ raise ValueError("Duration must be a non-negative integer.")
80
+
81
+ await target_member.timeout(until=datetime.now() + timedelta(seconds=duration), reason=reason)
82
+
83
+ return target_member.id
84
+
85
+
58
86
  async def dshell_rename_member(ctx: Message, new_name, member=None):
59
87
  """
60
88
  Renames a member in the server.
@@ -62,44 +90,97 @@ async def dshell_rename_member(ctx: Message, new_name, member=None):
62
90
  renamed_member = ctx.channel.guild.get_member(member)
63
91
 
64
92
  if not renamed_member:
65
- return 1 # Member not found in the server
93
+ raise Exception(f'Member {member} not found in the server !')
66
94
 
67
95
  await renamed_member.edit(nick=new_name)
68
96
 
69
97
  return renamed_member.id
70
98
 
71
- async def dshell_add_roles(ctx: Message, roles: list[int], member=None, reason: str = None):
99
+
100
+ async def dshell_add_roles(ctx: Message, roles: list[int] | int, member=None, reason: str = None):
72
101
  """
73
102
  Adds roles to a member in the server.
74
103
  """
75
104
  target_member: Member = ctx.author if member is None else ctx.channel.guild.get_member(member)
76
105
 
77
106
  if not target_member:
78
- return 1 # Member not found in the server
107
+ raise Exception(f'Member {member} not found in the server !')
108
+
109
+ if isinstance(roles, int):
110
+ roles = [roles]
79
111
 
80
112
  roles_to_add = [ctx.channel.guild.get_role(role_id) for role_id in roles if ctx.channel.guild.get_role(role_id)]
81
113
 
82
114
  if not roles_to_add:
83
- return 2 # No valid roles found
115
+ raise Exception(f'No role found !')
84
116
 
85
117
  await target_member.add_roles(*roles_to_add, reason=reason)
86
118
 
87
119
  return target_member.id
88
120
 
89
- async def dshell_remove_roles(ctx: Message, roles: list[int], member=None, reason: str = None):
121
+
122
+ async def dshell_remove_roles(ctx: Message, roles: list[int] | int, member=None, reason: str = None):
90
123
  """
91
124
  Removes roles from a member in the server.
92
125
  """
93
126
  target_member: Member = ctx.author if member is None else ctx.channel.guild.get_member(member)
94
127
 
95
128
  if not target_member:
96
- return 1 # Member not found in the server
129
+ raise Exception(f'Member {member} not found in the server !')
130
+
131
+ if isinstance(roles, int):
132
+ roles = [roles]
97
133
 
98
134
  roles_to_remove = [ctx.channel.guild.get_role(role_id) for role_id in roles if ctx.channel.guild.get_role(role_id)]
99
135
 
100
136
  if not roles_to_remove:
101
- return 2 # No valid roles found
137
+ raise Exception(f'No role found !')
102
138
 
103
139
  await target_member.remove_roles(*roles_to_remove, reason=reason)
104
140
 
105
- return target_member.id
141
+ return target_member.id
142
+
143
+
144
+ async def dshell_check_permissions(ctx: Message, permissions, member=None):
145
+ """
146
+ Checks if a member has specific permissions in the server.
147
+ """
148
+ target_member: Member = ctx.author if member is None else ctx.channel.guild.get_member(member)
149
+
150
+ if not target_member:
151
+ raise Exception(f'Member {member} not found in the server !')
152
+
153
+ if not isinstance(permissions, int):
154
+ raise TypeError("Permissions must be an integer representing permissions flags.")
155
+
156
+ permissions_to_check = Permissions(permissions)
157
+ member_permissions = target_member.guild_permissions
158
+
159
+ if (permissions_to_check.value & member_permissions.value) != 0:
160
+ return True
161
+ return False
162
+
163
+
164
+ async def dshell_move_member(ctx: Message, member=None, channel=None, disconnect: bool = False, reason=None):
165
+ """
166
+ Moves a member to another channel.
167
+ If channel is None, disconnect the member from their current voice channel.
168
+ """
169
+ target_member = ctx.author if member is None else ctx.channel.guild.get_member(member)
170
+ target_channel = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
171
+
172
+ if not target_member:
173
+ raise Exception(f'Member {member} not found in the server !')
174
+
175
+ if target_member.voice.channel is None:
176
+ raise Exception(f'Member {target_member.name} is not in a voice channel !')
177
+
178
+ if not target_channel:
179
+ raise Exception(f'Channel {channel} not found in the server !')
180
+
181
+ if disconnect:
182
+ await target_member.move_to(None, reason=reason)
183
+ else:
184
+ await target_member.move_to(target_channel, reason=reason)
185
+
186
+ return target_member.id
@@ -1,24 +1,27 @@
1
- from discord import Embed, Message
2
- from discord.ext import commands
3
1
  from re import search
4
2
 
3
+ from discord import Embed, Message
4
+ from discord.ext import commands
5
5
 
6
6
  __all__ = [
7
7
  'dshell_send_message',
8
8
  'dshell_delete_message',
9
9
  'dshell_purge_message',
10
10
  'dshell_edit_message',
11
- 'dshell_research_regex_message',
11
+ 'dshell_get_hystory_messages',
12
12
  'dshell_research_regex_in_content',
13
13
  'dshell_add_reactions',
14
14
  'dshell_remove_reactions'
15
15
  ]
16
16
 
17
17
 
18
- async def dshell_send_message(ctx: Message, message=None, delete=None, channel=None, embeds=None, embed=None):
18
+ async def dshell_send_message(ctx: Message, message=None, delete=None, channel=None, embeds=None):
19
19
  """
20
20
  Sends a message on Discord
21
21
  """
22
+ if delete is not None and not isinstance(delete, (int, float)):
23
+ raise Exception(f'Delete parameter must be a number (seconds) or None, not {type(delete)} !')
24
+
22
25
  channel_to_send = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
23
26
 
24
27
  if channel_to_send is None:
@@ -32,8 +35,8 @@ async def dshell_send_message(ctx: Message, message=None, delete=None, channel=N
32
35
  elif isinstance(embeds, Embed):
33
36
  embeds = ListNode([embeds])
34
37
 
35
- if embed is not None and isinstance(embed, Embed):
36
- embeds.add(embed)
38
+ else:
39
+ raise Exception(f'Embeds must be a list of Embed objects or a single Embed object, not {type(embeds)} !')
37
40
 
38
41
  sended_message = await channel_to_send.send(message,
39
42
  delete_after=delete,
@@ -47,7 +50,11 @@ async def dshell_delete_message(ctx: Message, message=None, reason=None, delay=0
47
50
  Deletes a message
48
51
  """
49
52
 
50
- delete_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)
53
+ delete_message = ctx if message is None else ctx.channel.get_partial_message(
54
+ message) # builds a reference to the message (even if it doesn't exist)
55
+
56
+ if not isinstance(delay, int):
57
+ raise Exception(f'Delete delay must be an integer, not {type(delay)} !')
51
58
 
52
59
  if delay > 3600:
53
60
  raise Exception(f'The message deletion delay is too long! ({delay} seconds)')
@@ -60,6 +67,9 @@ async def dshell_purge_message(ctx: Message, message_number, channel=None, reaso
60
67
  Purges messages from a channel
61
68
  """
62
69
 
70
+ if not isinstance(message_number, int):
71
+ raise Exception(f'Message number must be an integer, not {type(message_number)} !')
72
+
63
73
  purge_channel = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
64
74
 
65
75
  if purge_channel is None:
@@ -72,7 +82,8 @@ async def dshell_edit_message(ctx: Message, message, new_content=None, embeds=No
72
82
  """
73
83
  Edits a message
74
84
  """
75
- edit_message = ctx.channel.get_partial_message(message) # builds a reference to the message (even if it doesn't exist)
85
+ edit_message = ctx.channel.get_partial_message(
86
+ message) # builds a reference to the message (even if it doesn't exist)
76
87
 
77
88
  if embeds is None:
78
89
  embeds = []
@@ -84,11 +95,15 @@ async def dshell_edit_message(ctx: Message, message, new_content=None, embeds=No
84
95
 
85
96
  return edit_message.id
86
97
 
87
- async def dshell_research_regex_message(ctx: Message, regex, channel=None):
98
+
99
+ async def dshell_get_hystory_messages(ctx: Message, channel=None, limit=None):
88
100
  """
89
101
  Searches for messages matching a regex in a channel
90
102
  """
91
103
 
104
+ if limit is not None and not isinstance(limit, int):
105
+ raise Exception(f"Limit must be an integer or None, not {type(limit)}!")
106
+
92
107
  search_channel = ctx.channel if channel is None else ctx.channel.guild.get_channel(channel)
93
108
 
94
109
  if search_channel is None:
@@ -97,30 +112,35 @@ async def dshell_research_regex_message(ctx: Message, regex, channel=None):
97
112
  from .._DshellParser.ast_nodes import ListNode
98
113
 
99
114
  messages = ListNode([])
100
- async for message in search_channel.history(limit=100):
101
- if search(regex, message.content):
102
- messages.add(message)
115
+ async for message in search_channel.history(limit=limit):
116
+ messages.add(message)
103
117
 
104
118
  if not messages:
105
- raise commands.CommandError(f"No messages found matching the regex '{regex}'.")
119
+ raise commands.CommandError(f"No messages in {search_channel.mention}.")
106
120
 
107
121
  return messages
108
122
 
123
+
109
124
  async def dshell_research_regex_in_content(ctx: Message, regex, content=None):
110
125
  """
111
126
  Searches for a regex in a specific message content
112
127
  """
113
128
 
114
- if not search(regex, content if content is not None else ctx.content):
129
+ if not isinstance(regex, str):
130
+ raise Exception(f"Regex must be a string, not {type(regex)}!")
131
+
132
+ if not search(regex, str(content) if content is not None else ctx.content):
115
133
  return False
116
134
 
117
135
  return True
118
136
 
137
+
119
138
  async def dshell_add_reactions(ctx: Message, reactions, message=None):
120
139
  """
121
140
  Adds reactions to a message
122
141
  """
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)
142
+ message = ctx if message is None else ctx.channel.get_partial_message(
143
+ message) # builds a reference to the message (even if it doesn't exist)
124
144
 
125
145
  if isinstance(reactions, str):
126
146
  reactions = (reactions,)
@@ -130,11 +150,13 @@ async def dshell_add_reactions(ctx: Message, reactions, message=None):
130
150
 
131
151
  return message.id
132
152
 
153
+
133
154
  async def dshell_remove_reactions(ctx: Message, reactions, message=None):
134
155
  """
135
156
  Removes reactions from a message
136
157
  """
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)
158
+ message = ctx if message is None else ctx.channel.get_partial_message(
159
+ message) # builds a reference to the message (even if it doesn't exist)
138
160
 
139
161
  if isinstance(reactions, str):
140
162
  reactions = [reactions]
@@ -142,4 +164,4 @@ async def dshell_remove_reactions(ctx: Message, reactions, message=None):
142
164
  for reaction in reactions:
143
165
  await message.clear_reaction(reaction)
144
166
 
145
- return message.id
167
+ return message.id
@@ -0,0 +1,30 @@
1
+ from discord import Message
2
+ from requests import get
3
+
4
+ __all__ = [
5
+ 'dshell_get_pastbin'
6
+ ]
7
+
8
+
9
+ async def dshell_get_pastbin(ctx: Message, code: str):
10
+ """
11
+ Get a pastbin from a code snippet.
12
+ """
13
+ if not isinstance(code, str):
14
+ raise Exception(f'Code must be a string, not {type(code)} !')
15
+
16
+ content = '' # Initialize content to an empty string
17
+
18
+ with get(f"https://pastebin.com/raw/{code}", stream=True, timeout=10) as response:
19
+
20
+ if not response.ok:
21
+ raise Exception(f"Failed to retrieve pastbin with code {code} !")
22
+
23
+ for line in response.iter_lines(decode_unicode=True, chunk_size=512):
24
+ len_content = len(content)
25
+ if len_content < 4000 and len_content + len(line) <= 4000:
26
+ content += line + '\n'
27
+ else:
28
+ break
29
+
30
+ return content
@@ -0,0 +1,116 @@
1
+ from discord import MISSING, Message, Role, Permissions, PermissionOverwrite
2
+ from discord.utils import _MissingSentinel
3
+ from .._DshellInterpreteur.dshell_interpreter import build_colour, ListNode
4
+
5
+ __all__ = [
6
+ 'dshell_create_role',
7
+ 'dshell_delete_roles',
8
+ 'dshell_edit_role'
9
+
10
+ ]
11
+
12
+ async def dshell_create_role(ctx: Message,
13
+ name: str = MISSING,
14
+ permissions: dict[None, PermissionOverwrite] = MISSING,
15
+ color: int = MISSING,
16
+ hoist: bool = MISSING,
17
+ mentionable: bool = MISSING,
18
+ reason: str = None):
19
+ """
20
+ Creates a role on the server.
21
+ """
22
+ if not isinstance(name, (str, _MissingSentinel)):
23
+ raise Exception(f"Name must be a string, not {type(name)} !")
24
+
25
+ if not isinstance(permissions, (dict, _MissingSentinel)):
26
+ raise Exception(f"Permissions must be a PermissionNode, not {type(permissions)} !")
27
+
28
+ colour = build_colour(color)
29
+
30
+ if not isinstance(hoist, (bool, _MissingSentinel)):
31
+ raise Exception(f"Hoist must be a boolean, not {type(permissions)} !")
32
+
33
+ if not isinstance(mentionable, (bool, _MissingSentinel)):
34
+ raise Exception(f"Mentionable must be a boolean, not {type(permissions)} !")
35
+
36
+ if isinstance(permissions, dict):
37
+ if None in permissions:
38
+ allow, deny = permissions[None].pair()
39
+ permissions = allow
40
+
41
+ created_role = await ctx.guild.create_role(name=name,
42
+ permissions=permissions,
43
+ colour=colour,
44
+ hoist=hoist,
45
+ mentionable=mentionable,
46
+ reason=str(reason))
47
+
48
+ return created_role.id
49
+
50
+
51
+ async def dshell_delete_roles(ctx: Message, roles, reason=None):
52
+ """
53
+ Delete the role on the server
54
+ """
55
+ roles: int | ListNode
56
+ if not isinstance(roles, (int, ListNode)):
57
+ raise Exception(f"Role must be a int, role mention or NodeList of both, not {type(roles)} !")
58
+
59
+ if isinstance(roles, int):
60
+ roles: tuple = (roles, )
61
+
62
+ for i in roles:
63
+ role_to_delete = ctx.guild.get_role(i)
64
+
65
+ if role_to_delete is None:
66
+ raise Exception(f'Role {i} not found in the server !')
67
+
68
+ await role_to_delete.delete(reason=str(reason))
69
+
70
+
71
+ async def dshell_edit_role(ctx: Message,
72
+ role,
73
+ name=None,
74
+ permissions: dict[None, PermissionOverwrite]=None,
75
+ color=None,
76
+ hoist=None,
77
+ mentionable=None,
78
+ position=None,
79
+ reason=None,):
80
+ """
81
+ Edit the current role
82
+ """
83
+ if not isinstance(role, int):
84
+ raise Exception(f"Role must be a int or role mention not {type(role)} !")
85
+
86
+ role_to_edit = ctx.guild.get_role(role)
87
+
88
+ if not isinstance(name, (str, None)):
89
+ raise Exception(f"Name must be a string, not {type(name)} !")
90
+
91
+ if not isinstance(permissions, (dict, None)):
92
+ raise Exception(f"Permissions must be a PermissionNode, not {type(permissions)} !")
93
+
94
+ if isinstance(permissions, dict):
95
+ if None in permissions:
96
+ allow, deny = permissions[None].pair()
97
+ permissions = allow
98
+
99
+ colour = build_colour(color)
100
+
101
+ if not isinstance(hoist, (bool, None)):
102
+ raise Exception(f"Hoist must be a boolean, not {type(permissions)} !")
103
+
104
+ if not isinstance(mentionable, (bool, None)):
105
+ raise Exception(f"Mentionable must be a boolean, not {type(permissions)} !")
106
+
107
+ if not isinstance(position, (int, None)):
108
+ raise Exception(f"Position must be an integer, not {type(permissions)} !")
109
+
110
+ await role_to_edit.edit(name=name if name is not None else role_to_edit.name,
111
+ permissions=permissions if permissions is not None else role_to_edit.permissions,
112
+ colour=colour if color is not None else role_to_edit.colour,
113
+ hoist=hoist if hoist is not None else role_to_edit.hoist,
114
+ mentionable=mentionable if mentionable is not None else role_to_edit.mentionable,
115
+ position=position if position is not None else role_to_edit.position,
116
+ reason=str(reason))
@@ -33,7 +33,24 @@ class DshellInterpreteur:
33
33
  """
34
34
  self.ast: list[ASTNode] = parse(DshellTokenizer(code).start(), StartNode([]))[0]
35
35
  self.env: dict[str, Any] = {
36
- '__ret__': None} # environment variables, '__ret__' is used to store the return value of commands
36
+ '__ret__': None, # environment variables, '__ret__' is used to store the return value of commands
37
+ '__guild__': ctx.channel.guild.name,
38
+ '__channel__': ctx.channel.name,
39
+ '__author__': ctx.author.name,
40
+ '__author_display_name__': ctx.author.display_name,
41
+ '__author_avatar__': ctx.author.display_avatar.url if ctx.author.display_avatar else None,
42
+ '__author_discriminator__': ctx.author.discriminator,
43
+ '__author_bot__': ctx.author.bot,
44
+ '__author_nick__': ctx.author.nick if hasattr(ctx.author, 'nick') else None,
45
+ '__author_avatar_url__': ctx.author.avatar.url if ctx.author.avatar else None,
46
+ '__author_id__': ctx.author.id,
47
+ '__message__': ctx.content,
48
+ '__message_id__': ctx.id,
49
+ '__channel_name__': ctx.channel.name,
50
+ '__channel_type__': ctx.channel.type.name if hasattr(ctx.channel, 'type') else None,
51
+ '__channel_id__': ctx.channel.id,
52
+ '__private_channel__': isinstance(ctx.channel, PrivateChannel),
53
+ }
37
54
  self.vars = vars if vars is not None else ''
38
55
  self.ctx: context = ctx
39
56
  if debug:
@@ -170,12 +187,12 @@ def get_params(node: ParamNode, interpreter: DshellInterpreteur) -> dict[str, An
170
187
  englobe_args = regrouped_args.pop('--*', {}) # get the arguments that are not mandatory
171
188
  obligate = [i for i in regrouped_args.keys() if regrouped_args[i] == '*'] # get the obligatory parameters
172
189
 
173
-
174
190
  g: list[list[Token]] = DshellTokenizer(interpreter.vars).start()
175
191
  env_give_variables = regroupe_commandes(g[0], interpreter)[0] if g else {}
176
192
 
177
193
  gived_variables = env_give_variables.pop('*', ()) # get the variables given in the environment
178
- englobe_gived_variables: dict = env_give_variables.pop('--*', {}) # get the variables given in the environment that are not mandatory
194
+ englobe_gived_variables: dict = env_give_variables.pop('--*',
195
+ {}) # get the variables given in the environment that are not mandatory
179
196
 
180
197
  for key, value in zip(regrouped_args.keys(), gived_variables):
181
198
  regrouped_args[key] = value
@@ -187,7 +204,8 @@ def get_params(node: ParamNode, interpreter: DshellInterpreteur) -> dict[str, An
187
204
  del englobe_args[key]
188
205
  break
189
206
 
190
- for key, englobe_gived_key, englobe_gived_value in zip(englobe_args.keys(), englobe_gived_variables.keys(), englobe_gived_variables.values()):
207
+ for key, englobe_gived_key, englobe_gived_value in zip(englobe_args.keys(), englobe_gived_variables.keys(),
208
+ englobe_gived_variables.values()):
191
209
  if key == englobe_gived_key:
192
210
  regrouped_args[key] = englobe_gived_value
193
211
 
@@ -203,10 +221,9 @@ def get_params(node: ParamNode, interpreter: DshellInterpreteur) -> dict[str, An
203
221
  if regrouped_args[key] == '*':
204
222
  raise Exception(f"'{key}' is an obligatory parameter, but no value was given for it.")
205
223
 
206
- print(regrouped_args)
207
-
208
224
  return regrouped_args
209
225
 
226
+
210
227
  def eval_expression_inline(if_node: IfNode, interpreter: DshellInterpreteur) -> Token:
211
228
  """
212
229
  Eval a conditional expression inline.
@@ -312,7 +329,7 @@ def regroupe_commandes(body: list[Token], interpreter: DshellInterpreteur) -> li
312
329
  type_=DTT.SEPARATOR, value=body[i].value, position=body[i].position)
313
330
  ] + body[i + 1:], interpreter
314
331
  ) # add a sub-dictionary for sub-commands
315
- #return list_tokens
332
+ # return list_tokens
316
333
 
317
334
  elif (body[i].type == DTT.SEPARATOR and
318
335
  (body[i + 1].type == DTT.MATHS_OPERATOR and body[i + 1].value == '*') and
@@ -349,9 +366,8 @@ def build_embed(body: list[Token], fields: list[FieldEmbedNode], interpreter: Ds
349
366
  a: dict[str, Token]
350
367
  args_fields.append(a)
351
368
 
352
- if 'color' in args_main_embed and isinstance(args_main_embed['color'],
353
- ListNode): # if color is a ListNode, convert it to Colour
354
- args_main_embed['color'] = Colour.from_rgb(*args_main_embed['color'])
369
+ if 'color' in args_main_embed:
370
+ args_main_embed['color'] = build_colour(args_main_embed['color']) # convert color to Colour object or int
355
371
 
356
372
  embed = Embed(**args_main_embed) # build the main embed
357
373
  for field in args_fields:
@@ -359,6 +375,21 @@ def build_embed(body: list[Token], fields: list[FieldEmbedNode], interpreter: Ds
359
375
 
360
376
  return embed
361
377
 
378
+ def build_colour(color: Union[int, ListNode]) -> Union[Colour, int]:
379
+ """
380
+ Builds a Colour object from an integer or a ListNode.
381
+ :param color: The color to build.
382
+ :return: A Colour object.
383
+ """
384
+ if isinstance(color, int):
385
+ return color
386
+ elif isinstance(color, (ListNode, list)):
387
+ if not len(color) == 3:
388
+ raise ValueError(f"Color must be a list of 3 integers, not {len(color)} elements !")
389
+ return Colour.from_rgb(*color)
390
+ else:
391
+ raise TypeError(f"Color must be an integer or a ListNode, not {type(color)} !")
392
+
362
393
 
363
394
  def build_permission(body: list[Token], interpreter: DshellInterpreteur) -> dict[
364
395
  Union[Member, Role], PermissionOverwrite]:
@@ -429,9 +460,12 @@ class DshellPermissions:
429
460
  if member is not None:
430
461
  return member
431
462
 
432
- if role is not None:
463
+ elif role is not None:
433
464
  return role
434
465
 
466
+ else:
467
+ raise ValueError(f"No member or role found with ID {target_id} in guild {guild.name}.")
468
+
435
469
  @staticmethod
436
470
  def get_member(guild: Guild, target_id: int) -> Member:
437
471
  """
@@ -463,10 +497,11 @@ class DshellPermissions:
463
497
  def get_permission_overwrite(self, guild: Guild) -> dict[Union[Member, Role], PermissionOverwrite]:
464
498
  """
465
499
  Returns a PermissionOverwrite object with member and role permissions.
500
+ If no members or roles are specified, it returns a PermissionOverwrite with None key.
466
501
  :param guild: The Discord server
467
502
  :return: A dictionary of PermissionOverwrite objects with members and roles as keys
468
503
  """
469
- permissions: dict[Union[Member, Role], PermissionOverwrite] = {}
504
+ permissions: dict[Union[Member, Role, None], PermissionOverwrite] = {}
470
505
  target_keys = self.target.keys()
471
506
 
472
507
  if 'members' in target_keys:
@@ -489,6 +524,9 @@ class DshellPermissions:
489
524
  deny=Permissions(permissions=self.target.get('deny', 0))
490
525
  )
491
526
  else:
492
- raise ValueError("No members or roles specified in the permissions target.")
527
+ permissions[None] = PermissionOverwrite.from_pair(
528
+ allow=Permissions(permissions=self.target.get('allow', 0)),
529
+ deny=Permissions(permissions=self.target.get('deny', 0))
530
+ )
493
531
 
494
532
  return permissions
@@ -1,5 +1,5 @@
1
- from typing import Optional, Any
2
1
  from random import randint
2
+ from typing import Optional, Any
3
3
 
4
4
  from .._DshellTokenizer.dshell_token_type import Token
5
5
 
@@ -35,6 +35,7 @@ class StartNode(ASTNode):
35
35
  """
36
36
  Node representing the start of the AST.
37
37
  """
38
+
38
39
  def __init__(self, body: list):
39
40
  self.body = body
40
41
 
@@ -56,6 +57,7 @@ class ElseNode(ASTNode):
56
57
  """
57
58
  Node representing the 'else' part of an if statement.
58
59
  """
60
+
59
61
  def __init__(self, body: list[Token]):
60
62
  """
61
63
  :param body: list of tokens representing the body of the else statement
@@ -80,6 +82,7 @@ class ElifNode(ASTNode):
80
82
  """
81
83
  Node representing an 'elif' part of an if statement.
82
84
  """
85
+
83
86
  def __init__(self, condition: list[Token], body: list[Token], parent: "IfNode"):
84
87
  """
85
88
  :param condition: list of tokens representing the condition for the elif
@@ -110,6 +113,7 @@ class IfNode(ASTNode):
110
113
  """
111
114
  Node representing an 'if' statement, which can contain 'elif' and 'else' parts.
112
115
  """
116
+
113
117
  def __init__(self, condition: list[Token], body: list[Token], elif_nodes: Optional[list[ElifNode]] = None,
114
118
  else_body: Optional[ElseNode] = None):
115
119
  """
@@ -141,10 +145,12 @@ class IfNode(ASTNode):
141
145
  "id": self.id
142
146
  }
143
147
 
148
+
144
149
  class LoopNode(ASTNode):
145
150
  """
146
151
  Node representing a loop structure in the AST.
147
152
  """
153
+
148
154
  def __init__(self, variable: "VarNode", body: list):
149
155
  """
150
156
  :param variable: VarNode representing the loop variable. This variable will be used to iterate over the body. Can contain a ListNode, string or integer.
@@ -167,10 +173,12 @@ class LoopNode(ASTNode):
167
173
  "body": [token.to_dict() for token in self.body]
168
174
  }
169
175
 
176
+
170
177
  class ArgsCommandNode(ASTNode):
171
178
  """
172
179
  Node representing the arguments of a command in the AST.
173
180
  """
181
+
174
182
  def __init__(self, body: list[Token]):
175
183
  """
176
184
  :param body: list of tokens representing the arguments of the command
@@ -195,6 +203,7 @@ class CommandNode(ASTNode):
195
203
  """
196
204
  Node representing a command in the AST.
197
205
  """
206
+
198
207
  def __init__(self, name: str, body: ArgsCommandNode):
199
208
  """
200
209
  :param name: The command name (e.g., "sm", "cc")
@@ -222,6 +231,7 @@ class VarNode(ASTNode):
222
231
  """
223
232
  Node representing a variable declaration in the AST.
224
233
  """
234
+
225
235
  def __init__(self, name: Token, body: list[Token]):
226
236
  """
227
237
  :param name: Token representing the variable name
@@ -249,6 +259,7 @@ class EndNode(ASTNode):
249
259
  """
250
260
  Node representing the end of the AST.
251
261
  """
262
+
252
263
  def __init__(self):
253
264
  pass
254
265
 
@@ -269,6 +280,7 @@ class FieldEmbedNode(ASTNode):
269
280
  """
270
281
  Node representing a field in an embed structure.
271
282
  """
283
+
272
284
  def __init__(self, body: list[Token]):
273
285
  """
274
286
  :param body: list of tokens representing the field content
@@ -293,6 +305,7 @@ class EmbedNode(ASTNode):
293
305
  """
294
306
  Node representing an embed structure in the AST.
295
307
  """
308
+
296
309
  def __init__(self, body: list[Token], fields: list[FieldEmbedNode]):
297
310
  """
298
311
  :param body: list of tokens representing the embed content
@@ -320,6 +333,7 @@ class PermissionNode(ASTNode):
320
333
  """
321
334
  Node representing a permission structure in the AST.
322
335
  """
336
+
323
337
  def __init__(self, body: list[Token]):
324
338
  """
325
339
  :param body: list of tokens representing the permission content
@@ -344,6 +358,7 @@ class SleepNode(ASTNode):
344
358
  """
345
359
  Node representing a sleep command in the AST.
346
360
  """
361
+
347
362
  def __init__(self, body: list[Token]):
348
363
  """
349
364
  :param body: list of tokens representing the sleep duration
@@ -396,6 +411,7 @@ class IdentOperationNode(ASTNode):
396
411
  "args": self.args.to_dict()
397
412
  }
398
413
 
414
+
399
415
  class ParamNode(ASTNode):
400
416
  """
401
417
  Node representing a parameter in the AST.
@@ -423,6 +439,7 @@ class ParamNode(ASTNode):
423
439
  "body": [token.to_dict() for token in self.body]
424
440
  }
425
441
 
442
+
426
443
  class ListNode(ASTNode):
427
444
  """
428
445
  Node representing a list structure in the AST.
@@ -7,7 +7,7 @@ __all__ = [
7
7
  "ast_to_dict",
8
8
  ]
9
9
 
10
- from typing import Union, TYPE_CHECKING
10
+ from typing import Union
11
11
 
12
12
  from .ast_nodes import (ASTNode,
13
13
  CommandNode,
@@ -25,11 +25,10 @@ from .ast_nodes import (ASTNode,
25
25
  PermissionNode,
26
26
  ParamNode,
27
27
  StartNode)
28
+ from .._DshellTokenizer import dshell_operators
28
29
  from .._DshellTokenizer.dshell_token_type import DshellTokenType as DTT
29
30
  from .._DshellTokenizer.dshell_token_type import Token
30
31
 
31
- from .._DshellTokenizer import dshell_operators
32
-
33
32
 
34
33
  def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[ASTNode], int]:
35
34
  """
@@ -213,6 +212,7 @@ elif first_token_line.type == DTT.LIST: # si le token est une liste (qui comport
213
212
  last_block.body.append(list_node)
214
213
  """
215
214
 
215
+
216
216
  def ast_to_dict(obj):
217
217
  if isinstance(obj, list):
218
218
  return [ast_to_dict(item) for item in obj]
@@ -221,6 +221,7 @@ def ast_to_dict(obj):
221
221
  else:
222
222
  return obj # fallback for primitives or tokens
223
223
 
224
+
224
225
  def dict_to_ast(data):
225
226
  """
226
227
  Convertit un dictionnaire en une structure AST.
@@ -232,6 +233,7 @@ def dict_to_ast(data):
232
233
  elif isinstance(data, dict):
233
234
  pass
234
235
 
236
+
235
237
  def parser_inline(tokens: list[Token]) -> tuple[list[list[Token]], bool]:
236
238
  """
237
239
  Transforme une ligne avec un if/else inline en structure multilignes
@@ -10,8 +10,10 @@ __all__ = [
10
10
  from typing import Callable
11
11
 
12
12
  from ..DISCORD_COMMANDS.dshell_channel import *
13
- from ..DISCORD_COMMANDS.dshell_message import *
14
13
  from ..DISCORD_COMMANDS.dshell_member import *
14
+ from ..DISCORD_COMMANDS.dshell_message import *
15
+ from ..DISCORD_COMMANDS.dshell_pastbin import *
16
+ from ..DISCORD_COMMANDS.dshell_role import *
15
17
 
16
18
  dshell_keyword: set[str] = {
17
19
  'if', 'else', 'elif', 'loop', '#end', 'var', '#loop', '#if', 'sleep', 'param', '#param'
@@ -22,6 +24,8 @@ dshell_discord_keyword: set[str] = {
22
24
  }
23
25
  dshell_commands: dict[str, Callable] = {
24
26
 
27
+ "gp": dshell_get_pastbin, # get pastbin
28
+
25
29
  "sm": dshell_send_message, # send message
26
30
  "dm": dshell_delete_message,
27
31
  "pm": dshell_purge_message,
@@ -30,19 +34,26 @@ dshell_commands: dict[str, Callable] = {
30
34
  "cc": dshell_create_text_channel, # create channel
31
35
  "cvc": dshell_create_voice_channel, # create voice channel
32
36
  "dc": dshell_delete_channel, # delete channel
33
- "dcs": dshell_delete_channels, # delete several channels by name or regex
37
+ "dcs": dshell_delete_channels, # delete several channels by name or regex
34
38
 
35
39
  "bm": dshell_ban_member, # ban member
36
40
  "um": dshell_unban_member, # unban member
37
41
  "km": dshell_kick_member, # kick member
42
+ "tm": dshell_timeout_member, # timeout member
43
+ "mm": dshell_move_member, # move member to another channel
38
44
  "rm": dshell_rename_member, # rename member
45
+ "cp": dshell_check_permissions, # check permissions
39
46
 
40
- "srm": dshell_research_regex_message, # research regex in message
47
+ "ghm": dshell_get_hystory_messages, # research regex in message
41
48
  "src": dshell_research_regex_in_content, # research regex in content
42
49
 
43
50
  "ec": dshell_edit_text_channel, # edit text channel
44
51
  "evc": dshell_edit_voice_channel, # edit voice channel
45
52
 
53
+ "cr": dshell_create_role,
54
+ "dr": dshell_delete_roles,
55
+ "er": dshell_edit_role,
56
+
46
57
  "amr": dshell_add_reactions, # add reactions to a message
47
58
  "rmr": dshell_remove_reactions, # remove reactions from a message
48
59
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dshellInterpreter
3
- Version: 0.2.2
3
+ Version: 0.2.4
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
@@ -16,6 +16,7 @@ Requires-Python: >=3.9
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: py-cord==2.6.1
19
+ Requires-Dist: requests
19
20
  Dynamic: author
20
21
  Dynamic: author-email
21
22
  Dynamic: classifier
@@ -0,0 +1,21 @@
1
+ Dshell/__init__.py,sha256=UPvXnewe_8FX9aoevMA78UN1k8AY-u8LTY3vEVxaDxw,72
2
+ Dshell/DISCORD_COMMANDS/__init__.py,sha256=_oo_aMEju4gZg-MIbF8bKMVM6CWAF0AO9DxAlemaXMw,149
3
+ Dshell/DISCORD_COMMANDS/dshell_channel.py,sha256=2qnbI2tUu5sowJVOVkY4p-l6Gu-5Gw9BEP3MItScvV8,8939
4
+ Dshell/DISCORD_COMMANDS/dshell_member.py,sha256=KEdI14VTmDJm3zb4Mt-cFe71Jdsrolj6O8673Vzw4n8,5943
5
+ Dshell/DISCORD_COMMANDS/dshell_message.py,sha256=fLxj_Ns-krZgXEPijhWvBFLorvmbleR6JpVOR72BIa8,5180
6
+ Dshell/DISCORD_COMMANDS/dshell_pastbin.py,sha256=TkWFGRRTvhhJgvwkDFx9Fz4UM2UUFwxyq0laMVx0mUk,881
7
+ Dshell/DISCORD_COMMANDS/dshell_role.py,sha256=LKWodMLC0mvm7BgImHIVeBWGHPmJvAYAG0lD_dr31WI,4660
8
+ Dshell/_DshellInterpreteur/__init__.py,sha256=xy5-J-R3YmY99JF3NBHTRRLsComFxpjnCA5xacISctU,35
9
+ Dshell/_DshellInterpreteur/dshell_interpreter.py,sha256=dJS8frzNhKEvs-WdC7kwcZMZKefraWO4t8vLrFctjvA,22805
10
+ Dshell/_DshellParser/__init__.py,sha256=ONDfhZMvClqP_6tE8SLjp-cf3pXL-auQYnfYRrHZxC4,56
11
+ Dshell/_DshellParser/ast_nodes.py,sha256=2qwL_M0ELPia6L6gqwgV5hqprvyuo97cx3Zk2dVz09U,15341
12
+ Dshell/_DshellParser/dshell_parser.py,sha256=bdnVhx-MchM61J88fa9PimpAdwPtQumywJd-GoMqS8Q,15514
13
+ Dshell/_DshellTokenizer/__init__.py,sha256=LIQSRhDx2B9pmPx5ADMwwD0Xr9ybneVLhHH8qrJWw_s,172
14
+ Dshell/_DshellTokenizer/dshell_keywords.py,sha256=G9qdXr-d05QtmBdwTGa1qMDm7TDbIEkbx_-ERU97Ods,4664
15
+ Dshell/_DshellTokenizer/dshell_token_type.py,sha256=pWzvmj6EFGkDwNHooOAjdyysi1vZRVEostFIZSW1Ais,1483
16
+ Dshell/_DshellTokenizer/dshell_tokenizer.py,sha256=-EhwrfbcOcnAxOHWBE89531t25u6c6HmJuT1AKFn9Ew,7032
17
+ dshellinterpreter-0.2.4.dist-info/licenses/LICENSE,sha256=lNgcw1_xb7QENAQi3uHGymaFtbs0RV-ihiCd7AoLQjA,1082
18
+ dshellinterpreter-0.2.4.dist-info/METADATA,sha256=_1jLYXDZ0NAPjcLsFS8-BsgVMmQ6QZfwSH_bdNLGgV8,1120
19
+ dshellinterpreter-0.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
+ dshellinterpreter-0.2.4.dist-info/top_level.txt,sha256=B4CMhtmchGwPQJLuqUy0GhRG-0cUGxKL4GqEbCiB_vE,7
21
+ dshellinterpreter-0.2.4.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- Dshell/__init__.py,sha256=UPvXnewe_8FX9aoevMA78UN1k8AY-u8LTY3vEVxaDxw,72
2
- Dshell/DISCORD_COMMANDS/__init__.py,sha256=unbZE4sxFCbUQ4Qptr1BhWu-nwhvI2oRzcDLtRmX6Ug,92
3
- Dshell/DISCORD_COMMANDS/dshell_channel.py,sha256=_qHfhVaeXLQMI926AJI3uYpjDXxVNF3sZ84EwWU-jz0,6450
4
- Dshell/DISCORD_COMMANDS/dshell_member.py,sha256=4cmpcu9RGHVUOGcF9pSnnxh7kEJQWAel4BBQ6Vicvbs,3126
5
- Dshell/DISCORD_COMMANDS/dshell_message.py,sha256=L5upeKAsski5bNjQTwzMNc2fVnUoz5_9TitQ5qJMuF0,4460
6
- Dshell/_DshellInterpreteur/__init__.py,sha256=xy5-J-R3YmY99JF3NBHTRRLsComFxpjnCA5xacISctU,35
7
- Dshell/_DshellInterpreteur/dshell_interpreter.py,sha256=Amk1Q7KM8OD6Za_pbXZs7W6rXe6BPVqG_1NRejRlccs,20859
8
- Dshell/_DshellParser/__init__.py,sha256=ONDfhZMvClqP_6tE8SLjp-cf3pXL-auQYnfYRrHZxC4,56
9
- Dshell/_DshellParser/ast_nodes.py,sha256=-zFmSeb6FnvcXd2gB3koy93apVJ-PiCY8PTUFj-_bG8,15307
10
- Dshell/_DshellParser/dshell_parser.py,sha256=jCnwxY_J-_u1W_tEotQznp4_Y0aeAH4pTcPl6_Fx9f8,15525
11
- Dshell/_DshellTokenizer/__init__.py,sha256=LIQSRhDx2B9pmPx5ADMwwD0Xr9ybneVLhHH8qrJWw_s,172
12
- Dshell/_DshellTokenizer/dshell_keywords.py,sha256=10VctszIRg8AX5Nsr7kwRIjdwzUgTfrrJYbD7QfYR5s,4253
13
- Dshell/_DshellTokenizer/dshell_token_type.py,sha256=pWzvmj6EFGkDwNHooOAjdyysi1vZRVEostFIZSW1Ais,1483
14
- Dshell/_DshellTokenizer/dshell_tokenizer.py,sha256=-EhwrfbcOcnAxOHWBE89531t25u6c6HmJuT1AKFn9Ew,7032
15
- dshellinterpreter-0.2.2.dist-info/licenses/LICENSE,sha256=lNgcw1_xb7QENAQi3uHGymaFtbs0RV-ihiCd7AoLQjA,1082
16
- dshellinterpreter-0.2.2.dist-info/METADATA,sha256=FHBHS3RDbndDp8iF1WanbDw8NXV52P4qijbIKt3gSdk,1095
17
- dshellinterpreter-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
- dshellinterpreter-0.2.2.dist-info/top_level.txt,sha256=B4CMhtmchGwPQJLuqUy0GhRG-0cUGxKL4GqEbCiB_vE,7
19
- dshellinterpreter-0.2.2.dist-info/RECORD,,