feat(sysadmin): Add remote async target.
This commit is contained in:
@@ -263,11 +263,64 @@ class Exec(LionCog):
|
|||||||
description=_("Execute arbitrary code with Exec")
|
description=_("Execute arbitrary code with Exec")
|
||||||
)
|
)
|
||||||
@appcmd.describe(
|
@appcmd.describe(
|
||||||
string="Code to execute."
|
string="Code to execute.",
|
||||||
|
target="Cross-shard peer to async on."
|
||||||
)
|
)
|
||||||
async def async_cmd(self, ctx: LionContext, *, string: Optional[str] = None):
|
async def async_cmd(self, ctx: LionContext,
|
||||||
|
string: Optional[str] = None,
|
||||||
|
target: Optional[str] = None,
|
||||||
|
):
|
||||||
|
if target is not None:
|
||||||
|
if string is None:
|
||||||
|
try:
|
||||||
|
ctx.interaction, string = await input(
|
||||||
|
ctx.interaction, "Cross-shard async", "Code to execute?",
|
||||||
|
style=discord.TextStyle.long
|
||||||
|
)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
return
|
||||||
|
await ctx.interaction.response.defer(thinking=True)
|
||||||
|
if target not in shard_talk.peers:
|
||||||
|
# Invalid target
|
||||||
|
embed = discord.Embed(
|
||||||
|
description="Unknown peer {target}",
|
||||||
|
colour=discord.Colour.brand_red(),
|
||||||
|
)
|
||||||
|
await ctx.interaction.edit_original_response(embed=embed)
|
||||||
|
else:
|
||||||
|
# Send to given target
|
||||||
|
result = await self.talk_async(string).send(target)
|
||||||
|
if len(result) > 1900:
|
||||||
|
# Send as file
|
||||||
|
with StringIO(result) as fp:
|
||||||
|
fp.seek(0)
|
||||||
|
file = discord.File(fp, filename=f"output-{target}.md")
|
||||||
|
await ctx.reply(file=file)
|
||||||
|
elif result:
|
||||||
|
await ctx.reply(f"```md{result}```")
|
||||||
|
else:
|
||||||
|
await ctx.reply("Command completed, and had no output.")
|
||||||
|
else:
|
||||||
await ExecUI(ctx, string, ExecStyle.EXEC, ephemeral=False).run()
|
await ExecUI(ctx, string, ExecStyle.EXEC, ephemeral=False).run()
|
||||||
|
|
||||||
|
async def _peer_acmpl(self, interaction: discord.Interaction, partial: str):
|
||||||
|
"""
|
||||||
|
Autocomplete utility for peer targets parameters.
|
||||||
|
"""
|
||||||
|
appids = set(shard_talk.peers.keys())
|
||||||
|
results = [
|
||||||
|
appcmd.Choice(name=appid, value=appid)
|
||||||
|
for appid in appids
|
||||||
|
if partial.lower() in appid.lower()
|
||||||
|
]
|
||||||
|
if not results:
|
||||||
|
results = [
|
||||||
|
appcmd.Choice(name=f"No peers found matching {partial}", value=partial)
|
||||||
|
]
|
||||||
|
return results
|
||||||
|
|
||||||
|
async_cmd.autocomplete('target')(_peer_acmpl)
|
||||||
|
|
||||||
@commands.hybrid_command(
|
@commands.hybrid_command(
|
||||||
name=_p('command', 'eval'),
|
name=_p('command', 'eval'),
|
||||||
description=_p('command:eval', 'Execute arbitrary code with Eval')
|
description=_p('command:eval', 'Execute arbitrary code with Eval')
|
||||||
@@ -325,40 +378,33 @@ class Exec(LionCog):
|
|||||||
# Send as message
|
# Send as message
|
||||||
await ctx.reply(f"```md\n{output}```", ephemeral=True)
|
await ctx.reply(f"```md\n{output}```", ephemeral=True)
|
||||||
|
|
||||||
@asyncall_cmd.autocomplete('target')
|
asyncall_cmd.autocomplete('target')(_peer_acmpl)
|
||||||
async def asyncall_target_acmpl(self, interaction: discord.Interaction, partial: str):
|
|
||||||
appids = set(shard_talk.peers.keys())
|
|
||||||
results = [
|
|
||||||
appcmd.Choice(name=appid, value=appid)
|
|
||||||
for appid in appids
|
|
||||||
if partial.lower() in appid.lower()
|
|
||||||
]
|
|
||||||
if not results:
|
|
||||||
results = [
|
|
||||||
appcmd.Choice(name=f"No peers found matching {partial}", value="None")
|
|
||||||
]
|
|
||||||
return results
|
|
||||||
|
|
||||||
@commands.hybrid_command(
|
@commands.hybrid_command(
|
||||||
name=_('reload'),
|
name=_('reload'),
|
||||||
description=_("Reload a given LionBot extension. Launches an ExecUI.")
|
description=_("Reload a given LionBot extension. Launches an ExecUI.")
|
||||||
)
|
)
|
||||||
@appcmd.describe(
|
@appcmd.describe(
|
||||||
extension=_("Name of the extesion to reload. See autocomplete for options.")
|
extension=_("Name of the extension to reload. See autocomplete for options."),
|
||||||
|
force=_("Whether to force an extension reload even if it doesn't exist.")
|
||||||
)
|
)
|
||||||
@appcmd.guilds(*guild_ids)
|
@appcmd.guilds(*guild_ids)
|
||||||
async def reload_cmd(self, ctx: LionContext, extension: str):
|
async def reload_cmd(self, ctx: LionContext, extension: str, force: Optional[bool] = False):
|
||||||
"""
|
"""
|
||||||
This is essentially just a friendly wrapper to reload an extension.
|
This is essentially just a friendly wrapper to reload an extension.
|
||||||
It is equivalent to running "await bot.reload_extension(extension)" in eval,
|
It is equivalent to running "await bot.reload_extension(extension)" in eval,
|
||||||
with a slightly nicer interface through the autocomplete and error handling.
|
with a slightly nicer interface through the autocomplete and error handling.
|
||||||
"""
|
"""
|
||||||
if extension not in self.bot.extensions:
|
exists = (extension in self.bot.extensions)
|
||||||
|
if not (force or exists):
|
||||||
embed = discord.Embed(description=f"Unknown extension {extension}", colour=discord.Colour.red())
|
embed = discord.Embed(description=f"Unknown extension {extension}", colour=discord.Colour.red())
|
||||||
await ctx.reply(embed=embed)
|
await ctx.reply(embed=embed)
|
||||||
else:
|
else:
|
||||||
# Uses an ExecUI to simplify error handling and re-execution
|
# Uses an ExecUI to simplify error handling and re-execution
|
||||||
|
if exists:
|
||||||
string = f"await bot.reload_extension('{extension}')"
|
string = f"await bot.reload_extension('{extension}')"
|
||||||
|
else:
|
||||||
|
string = f"await bot.load_extension('{extension}')"
|
||||||
await ExecUI(ctx, string, ExecStyle.EVAL).run()
|
await ExecUI(ctx, string, ExecStyle.EVAL).run()
|
||||||
|
|
||||||
@reload_cmd.autocomplete('extension')
|
@reload_cmd.autocomplete('extension')
|
||||||
|
|||||||
Reference in New Issue
Block a user