-
Notifications
You must be signed in to change notification settings - Fork 1
/
cmd_control.py
237 lines (197 loc) · 8.41 KB
/
cmd_control.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
"""
Terminal menu for managing slash commands
Contains all the logic needed to sync slash commands.
"""
import discord
import configs.config as config
def print_commands(commands):
"""
Quick loop that prints all commands in a list.
"""
n = 0
for i in commands:
print(f"[{n}] Name: {i.name} Desc: {i.description}")
n += 1
def restore_commands(command_tree, commands):
"""
Clears the commands in the command tree and replaces it with the
list of commands provided.
"""
# need to ensure no conflicts
command_tree.clear_commands(guild=None)
for i in commands:
command_tree.add_command(i)
async def local_commands(command_tree):
"""
Show details for commands loaded from local code. These commands are of type
discord.app_commands.Command.
"""
def get_params_str(params):
"""
Take a parameter and turn it into a string
"""
r_string = ""
for i in params:
r_string = "\t" + i.name + "\n"
return r_string
def parse_command(command):
"""
Pretty print a Discord.Command
"""
details = (f"Detailed info for command [{command.name}]: \n"
+ f"Desc: {command.description}\n"
+ f"Guild Only: {command.guild_only}\n"
+ f"Parent: {command.parent}\n"
+ "Usage Permissions Requirement Integer: ")
if command.default_permissions is None:
details = details + "None (Likely Default)\n"
else:
details = details + str(command.value) + "\n"
details = details + (f"Parameters:\n{get_params_str(command.parameters)}"
+ f"Extra Data: {command.extras}")
return details
print("\nFetching local application commands...")
commands = command_tree.get_commands()
print("\nLocal commands, loaded from the code on your machine:")
print_commands(commands)
while True:
response = input("\nEnter a number to view detailed info and/or remove the command, "
+ "'x' to remove all commands, 'p' to re-print, and 'q' to go back: ")
if response in {'q', 'Q'}:
return
if response in {'p', 'P'}:
print("\nFetching local application commands...")
commands = command_tree.get_commands()
print("\nLocal commands, loaded from the code on your machine:")
print_commands(commands)
elif response in {'x', 'X'}:
print("\nClearing the local command tree...")
command_tree.clear_commands(guild=None)
print("\nCommand tree cleared.")
return
elif response.isdigit():
response = int(response)
if response >= len(commands):
print("\nInvalid command nummber.")
continue
command = commands[response]
print(parse_command(command))
response = input("\nRemove command? y/N: ")
if response in {'y', 'Y'}:
command_tree.remove_command(command.name)
print("\nCommand removed.")
print("\nFetching local application commands...")
commands = command_tree.get_commands()
print("\nLocal commands, loaded from the code on your machine:")
print_commands(commands)
else:
print("Unrecognized command.")
async def synced_commands(command_tree):
"""
Show details for commands loaded from local code. These commands are of type
discord.app_commands.AppCommand.
"""
def parse_app_command(command):
"""
Pretty print a Discord.AppCommand
"""
details = (f"Detailed info for command [{command.name}]: \n"
+ f"Desc: {command.description}\n"
+ f"Command ID: {command.id}\n"
+ f"Guild ID: {command.guild_id}\n"
+ f"Application ID: {command.application_id}\n"
+ f"DM Permission: {command.dm_permission}\n"
+ "Usage Permissions Requirement Integer: ")
if command.default_member_permissions is None:
return details + "None (Likely Default)"
return details + str(command.value)
response = input("\nFetch global commands? y/N: ")
if response in {'y', 'Y'}:
# Global commands
print("\nFetching existing global application commands...")
commands = await command_tree.fetch_commands()
else:
# Local commands
response = input("\nWhich guild ID do you want to fetch the commands from? "
+ "(Enter nothing to use default): ")
if not response.isdigit():
print("\nFetching existing commands from default guild...")
commands = await command_tree.fetch_commands(guild=discord.Object(config.GUILD_ID))
else:
print("\nFetching existing commands from guild " + response + "...")
commands = await command_tree.fetch_commands(guild=discord.Object(int(response)))
print("\nExisting application commands:")
print_commands(commands)
while True:
response = input("\nEnter a number to view detailed info about the command, "
+ "'p' to re-print, and 'q' to go back: ")
if response in {'q', 'Q'}:
return
if response in {'p', 'P'}:
print_commands(commands)
elif response.isdigit():
response = int(response)
if response >= len(commands):
print("Invalid command number.")
continue
command = commands[response]
print(parse_app_command(command))
else:
print("Unrecognized command.")
async def command_control(command_tree):
"""
Input loop designed to handle syncing of commands.
"""
# save a copy of existing commands
local_command_list = command_tree.get_commands()
while True:
response = input("\nEnter 'l' to view local commands, 'v' to view the synced commands, "
+ "'s' to sync commands, 'e' to restore removed local commands, and 'r' "
+ "to run the bot: ")
if response in {'l', 'L'}:
await local_commands(command_tree)
elif response in {'v', 'V'}:
await synced_commands(command_tree)
elif response in {'s', 'S'}:
inner_response = input("\nSync globally? y/N: ")
local_guild = True
if inner_response in {'y', 'Y'}:
local_guild = False
if local_guild:
# Sync to local guild
response = input("\nWhich guild ID? (Enter nothing to use default): ")
if response.isdigit():
response = int(response)
else:
response = config.GUILD_ID
inner_response = input("\nThis will overwrite existing commands for guild "
+ str(response) + ". Are you sure? Y/n: ")
if inner_response in {'n', 'N'}:
print("Aborted.")
continue
# Copy the global commands to a guild, sync those commands, clean up
command_tree.copy_global_to(guild=discord.Object(response))
await command_tree.sync(guild=discord.Object(response))
# When a guild command is not found (which it won't, because this is clearing it)
# it will fallback on a version of the command not associated with any guild.
# This will always exist since we restore before running
command_tree.clear_commands(guild=discord.Object(response))
continue
# Sync globally
inner_response = input("\nThis will overwrite existing global commands. It "
+ "may also take up to an hour to register. "
+ "Are you sure? Y/n: ")
if inner_response in {'n', 'N'}:
print("Aborted.")
continue
await command_tree.sync()
continue
elif response in {'e', 'E'}:
restore_commands(command_tree, local_command_list)
elif response in {'r', 'R'}:
# Ensure that all commands are still available on the backend, even if they
# can't be called
restore_commands(command_tree, local_command_list)
return
else:
print("Unrecognized command.")