mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-21 18:27:59 -05:00
Merge branch 'V3/develop' into cog_guide_core
# Conflicts: # redbot/core/core_commands.py
This commit is contained in:
@@ -110,6 +110,7 @@ class RedBase(
|
||||
help__delete_delay=0,
|
||||
help__use_menus=False,
|
||||
help__show_hidden=False,
|
||||
help__show_aliases=True,
|
||||
help__verify_checks=True,
|
||||
help__verify_exists=False,
|
||||
help__tagline="",
|
||||
@@ -281,6 +282,92 @@ class RedBase(
|
||||
"""
|
||||
self._help_formatter = commands.help.RedHelpFormatter()
|
||||
|
||||
def add_dev_env_value(self, name: str, value: Callable[[commands.Context], Any]):
|
||||
"""
|
||||
Add a custom variable to the dev environment (``[p]debug``, ``[p]eval``, and ``[p]repl`` commands).
|
||||
If dev mode is disabled, nothing will happen.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class MyCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
bot.add_dev_env_value("mycog", lambda ctx: self)
|
||||
bot.add_dev_env_value("mycogdata", lambda ctx: self.settings[ctx.guild.id])
|
||||
|
||||
def cog_unload(self):
|
||||
self.bot.remove_dev_env_value("mycog")
|
||||
self.bot.remove_dev_env_value("mycogdata")
|
||||
|
||||
Once your cog is loaded, the custom variables ``mycog`` and ``mycogdata``
|
||||
will be included in the environment of dev commands.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name: str
|
||||
The name of your custom variable.
|
||||
value: Callable[[commands.Context], Any]
|
||||
The function returning the value of the variable.
|
||||
It must take a `commands.Context` as its sole parameter
|
||||
|
||||
Raises
|
||||
------
|
||||
TypeError
|
||||
``value`` argument isn't a callable.
|
||||
ValueError
|
||||
The passed callable takes no or more than one argument.
|
||||
RuntimeError
|
||||
The name of the custom variable is either reserved by a variable
|
||||
from the default environment or already taken by some other custom variable.
|
||||
"""
|
||||
signature = inspect.signature(value)
|
||||
if len(signature.parameters) != 1:
|
||||
raise ValueError("Callable must take exactly one argument for context")
|
||||
dev = self.get_cog("Dev")
|
||||
if dev is None:
|
||||
return
|
||||
if name in [
|
||||
"bot",
|
||||
"ctx",
|
||||
"channel",
|
||||
"author",
|
||||
"guild",
|
||||
"message",
|
||||
"asyncio",
|
||||
"aiohttp",
|
||||
"discord",
|
||||
"commands",
|
||||
"_",
|
||||
"__name__",
|
||||
"__builtins__",
|
||||
]:
|
||||
raise RuntimeError(f"The name {name} is reserved for default environement.")
|
||||
if name in dev.env_extensions:
|
||||
raise RuntimeError(f"The name {name} is already used.")
|
||||
dev.env_extensions[name] = value
|
||||
|
||||
def remove_dev_env_value(self, name: str):
|
||||
"""
|
||||
Remove a custom variable from the dev environment.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name: str
|
||||
The name of the custom variable.
|
||||
|
||||
Raises
|
||||
------
|
||||
KeyError
|
||||
The custom variable was never set.
|
||||
"""
|
||||
dev = self.get_cog("Dev")
|
||||
if dev is None:
|
||||
return
|
||||
del dev.env_extensions[name]
|
||||
|
||||
def get_command(self, name: str) -> Optional[commands.Command]:
|
||||
com = super().get_command(name)
|
||||
assert com is None or isinstance(com, commands.Command)
|
||||
@@ -383,6 +470,12 @@ class RedBase(
|
||||
self._red_before_invoke_objs.add(coro)
|
||||
return coro
|
||||
|
||||
async def before_identify_hook(self, shard_id, *, initial=False):
|
||||
"""A hook that is called before IDENTIFYing a session.
|
||||
Same as in discord.py, but also dispatches "on_red_identify" bot event."""
|
||||
self.dispatch("red_before_identify", shard_id, initial)
|
||||
return await super().before_identify_hook(shard_id, initial=initial)
|
||||
|
||||
@property
|
||||
def cog_mgr(self) -> NoReturn:
|
||||
raise AttributeError("Please don't mess with the cog manager internals.")
|
||||
|
||||
@@ -42,7 +42,7 @@ from ..i18n import Translator
|
||||
from ..utils import menus
|
||||
from ..utils.mod import mass_purge
|
||||
from ..utils._internal_utils import fuzzy_command_search, format_fuzzy_results
|
||||
from ..utils.chat_formatting import box, pagify, humanize_timedelta
|
||||
from ..utils.chat_formatting import box, humanize_list, humanize_number, humanize_timedelta, pagify
|
||||
|
||||
__all__ = ["red_help", "RedHelpFormatter", "HelpSettings", "HelpFormatterABC"]
|
||||
|
||||
@@ -72,6 +72,7 @@ class HelpSettings:
|
||||
max_pages_in_guild: int = 2
|
||||
use_menus: bool = False
|
||||
show_hidden: bool = False
|
||||
show_aliases: bool = True
|
||||
verify_checks: bool = True
|
||||
verify_exists: bool = False
|
||||
tagline: str = ""
|
||||
@@ -300,10 +301,42 @@ class RedHelpFormatter(HelpFormatterABC):
|
||||
|
||||
tagline = (help_settings.tagline) or self.get_default_tagline(ctx)
|
||||
signature = _(
|
||||
"`Syntax: {ctx.clean_prefix}{command.qualified_name} {command.signature}`"
|
||||
"Syntax: {ctx.clean_prefix}{command.qualified_name} {command.signature}"
|
||||
).format(ctx=ctx, command=command)
|
||||
subcommands = None
|
||||
|
||||
aliases = command.aliases
|
||||
if help_settings.show_aliases and aliases:
|
||||
alias_fmt = _("Aliases") if len(command.aliases) > 1 else _("Alias")
|
||||
aliases = sorted(aliases, key=len)
|
||||
|
||||
a_counter = 0
|
||||
valid_alias_list = []
|
||||
for alias in aliases:
|
||||
if (a_counter := a_counter + len(alias)) < 500:
|
||||
valid_alias_list.append(alias)
|
||||
else:
|
||||
break
|
||||
|
||||
a_diff = len(aliases) - len(valid_alias_list)
|
||||
aliases_list = [
|
||||
f"{ctx.clean_prefix}{command.parent.qualified_name + ' ' if command.parent else ''}{alias}"
|
||||
for alias in valid_alias_list
|
||||
]
|
||||
if len(valid_alias_list) < 10:
|
||||
aliases_content = humanize_list(aliases_list)
|
||||
else:
|
||||
aliases_formatted_list = ", ".join(aliases_list)
|
||||
if a_diff > 1:
|
||||
aliases_content = _("{aliases} and {number} more aliases.").format(
|
||||
aliases=aliases_formatted_list, number=humanize_number(a_diff)
|
||||
)
|
||||
else:
|
||||
aliases_content = _("{aliases} and one more alias.").format(
|
||||
aliases=aliases_formatted_list
|
||||
)
|
||||
signature += f"\n{alias_fmt}: {aliases_content}"
|
||||
|
||||
subcommands = None
|
||||
if hasattr(command, "all_commands"):
|
||||
grp = cast(commands.Group, command)
|
||||
subcommands = await self.get_group_help_mapping(ctx, grp, help_settings=help_settings)
|
||||
@@ -315,7 +348,7 @@ class RedHelpFormatter(HelpFormatterABC):
|
||||
emb["embed"]["title"] = f"*{description[:250]}*"
|
||||
|
||||
emb["footer"]["text"] = tagline
|
||||
emb["embed"]["description"] = signature
|
||||
emb["embed"]["description"] = box(signature)
|
||||
|
||||
command_help = command.format_help_for_context(ctx)
|
||||
if command_help:
|
||||
@@ -375,7 +408,7 @@ class RedHelpFormatter(HelpFormatterABC):
|
||||
None,
|
||||
(
|
||||
description,
|
||||
signature[1:-1],
|
||||
signature,
|
||||
command.format_help_for_context(ctx),
|
||||
subtext_header,
|
||||
subtext,
|
||||
|
||||
@@ -172,6 +172,20 @@ class CoreLogic:
|
||||
except errors.CogLoadError as e:
|
||||
failed_with_reason_packages.append((name, str(e)))
|
||||
except Exception as e:
|
||||
if isinstance(e, commands.CommandRegistrationError):
|
||||
if e.alias_conflict:
|
||||
error_message = _(
|
||||
"Alias {alias_name} is already an existing command"
|
||||
" or alias in one of the loaded cogs."
|
||||
).format(alias_name=inline(e.name))
|
||||
else:
|
||||
error_message = _(
|
||||
"Command {command_name} is already an existing command"
|
||||
" or alias in one of the loaded cogs."
|
||||
).format(command_name=inline(e.name))
|
||||
failed_with_reason_packages.append((name, error_message))
|
||||
continue
|
||||
|
||||
log.exception("Package loading failed", exc_info=e)
|
||||
|
||||
exception_log = "Exception during loading of package\n"
|
||||
@@ -2094,7 +2108,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
|
||||
if game:
|
||||
if len(game) > 128:
|
||||
await ctx.send("The maximum length of game descriptions is 128 characters.")
|
||||
await ctx.send(_("The maximum length of game descriptions is 128 characters."))
|
||||
return
|
||||
game = discord.Game(name=game)
|
||||
else:
|
||||
@@ -2126,6 +2140,11 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
|
||||
status = ctx.bot.guilds[0].me.status if len(ctx.bot.guilds) > 0 else discord.Status.online
|
||||
if listening:
|
||||
if len(listening) > 128:
|
||||
await ctx.send(
|
||||
_("The maximum length of listening descriptions is 128 characters.")
|
||||
)
|
||||
return
|
||||
activity = discord.Activity(name=listening, type=discord.ActivityType.listening)
|
||||
else:
|
||||
activity = None
|
||||
@@ -2157,6 +2176,9 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
|
||||
status = ctx.bot.guilds[0].me.status if len(ctx.bot.guilds) > 0 else discord.Status.online
|
||||
if watching:
|
||||
if len(watching) > 128:
|
||||
await ctx.send(_("The maximum length of watching descriptions is 128 characters."))
|
||||
return
|
||||
activity = discord.Activity(name=watching, type=discord.ActivityType.watching)
|
||||
else:
|
||||
activity = None
|
||||
@@ -2186,6 +2208,11 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
|
||||
status = ctx.bot.guilds[0].me.status if len(ctx.bot.guilds) > 0 else discord.Status.online
|
||||
if competing:
|
||||
if len(competing) > 128:
|
||||
await ctx.send(
|
||||
_("The maximum length of competing descriptions is 128 characters.")
|
||||
)
|
||||
return
|
||||
activity = discord.Activity(name=competing, type=discord.ActivityType.competing)
|
||||
else:
|
||||
activity = None
|
||||
@@ -2234,11 +2261,13 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
await ctx.bot.change_presence(status=status, activity=game)
|
||||
await ctx.send(_("Status changed to {}.").format(status))
|
||||
|
||||
@_set.command(name="streaming", aliases=["stream"], usage="[(<streamer> <stream_title>)]")
|
||||
@_set.command(
|
||||
name="streaming", aliases=["stream", "twitch"], usage="[(<streamer> <stream_title>)]"
|
||||
)
|
||||
@checks.bot_in_a_guild()
|
||||
@checks.is_owner()
|
||||
async def stream(self, ctx: commands.Context, streamer=None, *, stream_title=None):
|
||||
"""Sets [botname]'s streaming status.
|
||||
"""Sets [botname]'s streaming status to a twitch stream.
|
||||
|
||||
This will appear as `Streaming <stream_title>` or `LIVE ON TWITCH` depending on the context.
|
||||
It will also include a `Watch` button with a twitch.tv url for the provided streamer.
|
||||
@@ -2262,6 +2291,12 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
stream_title = stream_title.strip()
|
||||
if "twitch.tv/" not in streamer:
|
||||
streamer = "https://www.twitch.tv/" + streamer
|
||||
if len(streamer) > 511:
|
||||
await ctx.send(_("The maximum length of the streamer url is 511 characters."))
|
||||
return
|
||||
if len(stream_title) > 128:
|
||||
await ctx.send(_("The maximum length of the stream title is 128 characters."))
|
||||
return
|
||||
activity = discord.Streaming(url=streamer, name=stream_title)
|
||||
await ctx.bot.change_presence(status=status, activity=activity)
|
||||
elif streamer is not None:
|
||||
@@ -2782,6 +2817,22 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
else:
|
||||
await ctx.send(_("Help will filter hidden commands."))
|
||||
|
||||
@helpset.command(name="showaliases")
|
||||
async def helpset_showaliases(self, ctx: commands.Context, show_aliases: bool = None):
|
||||
"""
|
||||
This allows the help command to show existing commands aliases if there is any.
|
||||
|
||||
This defaults to True.
|
||||
Using this without a setting will toggle.
|
||||
"""
|
||||
if show_aliases is None:
|
||||
show_aliases = not await ctx.bot._config.help.show_aliases()
|
||||
await ctx.bot._config.help.show_aliases.set(show_aliases)
|
||||
if show_aliases:
|
||||
await ctx.send(_("Help will show commands aliases."))
|
||||
else:
|
||||
await ctx.send(_("Help will not show commands aliases."))
|
||||
|
||||
@helpset.command(name="usetick")
|
||||
async def helpset_usetick(self, ctx: commands.Context, use_tick: bool = None):
|
||||
"""
|
||||
@@ -3275,8 +3326,10 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
"""
|
||||
uids = {getattr(user, "id", user) for user in users}
|
||||
await self.bot._whiteblacklist_cache.add_to_whitelist(None, uids)
|
||||
|
||||
await ctx.send(_("Users added to allowlist."))
|
||||
if len(users) > 1:
|
||||
await ctx.send(_("Users have been added to the allowlist."))
|
||||
else:
|
||||
await ctx.send(_("User has been added to the allowlist."))
|
||||
|
||||
@allowlist.command(name="list")
|
||||
async def allowlist_list(self, ctx: commands.Context):
|
||||
@@ -3291,8 +3344,10 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
if not curr_list:
|
||||
await ctx.send("Allowlist is empty.")
|
||||
return
|
||||
|
||||
msg = _("Users on allowlist:")
|
||||
if len(curr_list) > 1:
|
||||
msg = _("Users on the allowlist:")
|
||||
else:
|
||||
msg = _("User on the allowlist:")
|
||||
for user in curr_list:
|
||||
msg += "\n\t- {}".format(user)
|
||||
|
||||
@@ -3316,8 +3371,10 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
"""
|
||||
uids = {getattr(user, "id", user) for user in users}
|
||||
await self.bot._whiteblacklist_cache.remove_from_whitelist(None, uids)
|
||||
|
||||
await ctx.send(_("Users have been removed from the allowlist."))
|
||||
if len(users) > 1:
|
||||
await ctx.send(_("Users have been removed from the allowlist."))
|
||||
else:
|
||||
await ctx.send(_("User has been removed from the allowlist."))
|
||||
|
||||
@allowlist.command(name="clear")
|
||||
async def allowlist_clear(self, ctx: commands.Context):
|
||||
@@ -3366,8 +3423,10 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
|
||||
uids = {getattr(user, "id", user) for user in users}
|
||||
await self.bot._whiteblacklist_cache.add_to_blacklist(None, uids)
|
||||
|
||||
await ctx.send(_("User added to blocklist."))
|
||||
if len(users) > 1:
|
||||
await ctx.send(_("Users have been added to the blocklist."))
|
||||
else:
|
||||
await ctx.send(_("User has been added to the blocklist."))
|
||||
|
||||
@blocklist.command(name="list")
|
||||
async def blocklist_list(self, ctx: commands.Context):
|
||||
@@ -3382,8 +3441,10 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
if not curr_list:
|
||||
await ctx.send("Blocklist is empty.")
|
||||
return
|
||||
|
||||
msg = _("Users on blocklist:")
|
||||
if len(curr_list) > 1:
|
||||
msg = _("Users on the blocklist:")
|
||||
else:
|
||||
msg = _("User on the blocklist:")
|
||||
for user in curr_list:
|
||||
msg += "\n\t- {}".format(user)
|
||||
|
||||
@@ -3405,8 +3466,10 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
"""
|
||||
uids = {getattr(user, "id", user) for user in users}
|
||||
await self.bot._whiteblacklist_cache.remove_from_blacklist(None, uids)
|
||||
|
||||
await ctx.send(_("Users have been removed from blocklist."))
|
||||
if len(users) > 1:
|
||||
await ctx.send(_("Users have been removed from the blocklist."))
|
||||
else:
|
||||
await ctx.send(_("User has been removed from the blocklist."))
|
||||
|
||||
@blocklist.command(name="clear")
|
||||
async def blocklist_clear(self, ctx: commands.Context):
|
||||
@@ -3468,7 +3531,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
@localallowlist.command(name="list")
|
||||
async def localallowlist_list(self, ctx: commands.Context):
|
||||
"""
|
||||
Lists users and roles on the server allowlist.
|
||||
Lists users and roles on the server allowlist.
|
||||
|
||||
Example:
|
||||
- `[p]localallowlist list`
|
||||
@@ -3478,8 +3541,10 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
if not curr_list:
|
||||
await ctx.send("Server allowlist is empty.")
|
||||
return
|
||||
|
||||
msg = _("Whitelisted Users and roles:")
|
||||
if len(curr_list) > 1:
|
||||
msg = _("Allowed users and/or roles:")
|
||||
else:
|
||||
msg = _("Allowed user or role:")
|
||||
for obj in curr_list:
|
||||
msg += "\n\t- {}".format(obj)
|
||||
|
||||
@@ -3593,8 +3658,10 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
if not curr_list:
|
||||
await ctx.send("Server blocklist is empty.")
|
||||
return
|
||||
|
||||
msg = _("Blacklisted Users and Roles:")
|
||||
if len(curr_list) > 1:
|
||||
msg = _("Blocked users and/or roles:")
|
||||
else:
|
||||
msg = _("Blocked user or role:")
|
||||
for obj in curr_list:
|
||||
msg += "\n\t- {}".format(obj)
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ class Dev(commands.Cog):
|
||||
super().__init__()
|
||||
self._last_result = None
|
||||
self.sessions = {}
|
||||
self.env_extensions = {}
|
||||
|
||||
@staticmethod
|
||||
def async_compile(source, filename, mode):
|
||||
@@ -92,6 +93,29 @@ class Dev(commands.Cog):
|
||||
token = ctx.bot.http.token
|
||||
return re.sub(re.escape(token), "[EXPUNGED]", input_, re.I)
|
||||
|
||||
def get_environment(self, ctx: commands.Context) -> dict:
|
||||
env = {
|
||||
"bot": ctx.bot,
|
||||
"ctx": ctx,
|
||||
"channel": ctx.channel,
|
||||
"author": ctx.author,
|
||||
"guild": ctx.guild,
|
||||
"message": ctx.message,
|
||||
"asyncio": asyncio,
|
||||
"aiohttp": aiohttp,
|
||||
"discord": discord,
|
||||
"commands": commands,
|
||||
"_": self._last_result,
|
||||
"__name__": "__main__",
|
||||
}
|
||||
for name, value in self.env_extensions.items():
|
||||
try:
|
||||
env[name] = value(ctx)
|
||||
except Exception as e:
|
||||
traceback.clear_frames(e.__traceback__)
|
||||
env[name] = e
|
||||
return env
|
||||
|
||||
@commands.command()
|
||||
@checks.is_owner()
|
||||
async def debug(self, ctx, *, code):
|
||||
@@ -115,21 +139,7 @@ class Dev(commands.Cog):
|
||||
commands - redbot.core.commands
|
||||
_ - The result of the last dev command.
|
||||
"""
|
||||
env = {
|
||||
"bot": ctx.bot,
|
||||
"ctx": ctx,
|
||||
"channel": ctx.channel,
|
||||
"author": ctx.author,
|
||||
"guild": ctx.guild,
|
||||
"message": ctx.message,
|
||||
"asyncio": asyncio,
|
||||
"aiohttp": aiohttp,
|
||||
"discord": discord,
|
||||
"commands": commands,
|
||||
"_": self._last_result,
|
||||
"__name__": "__main__",
|
||||
}
|
||||
|
||||
env = self.get_environment(ctx)
|
||||
code = self.cleanup_code(code)
|
||||
|
||||
try:
|
||||
@@ -169,21 +179,7 @@ class Dev(commands.Cog):
|
||||
commands - redbot.core.commands
|
||||
_ - The result of the last dev command.
|
||||
"""
|
||||
env = {
|
||||
"bot": ctx.bot,
|
||||
"ctx": ctx,
|
||||
"channel": ctx.channel,
|
||||
"author": ctx.author,
|
||||
"guild": ctx.guild,
|
||||
"message": ctx.message,
|
||||
"asyncio": asyncio,
|
||||
"aiohttp": aiohttp,
|
||||
"discord": discord,
|
||||
"commands": commands,
|
||||
"_": self._last_result,
|
||||
"__name__": "__main__",
|
||||
}
|
||||
|
||||
env = self.get_environment(ctx)
|
||||
body = self.cleanup_code(body)
|
||||
stdout = io.StringIO()
|
||||
|
||||
@@ -224,19 +220,6 @@ class Dev(commands.Cog):
|
||||
backtick. This includes codeblocks, and as such multiple lines can be
|
||||
evaluated.
|
||||
"""
|
||||
variables = {
|
||||
"ctx": ctx,
|
||||
"bot": ctx.bot,
|
||||
"message": ctx.message,
|
||||
"guild": ctx.guild,
|
||||
"channel": ctx.channel,
|
||||
"author": ctx.author,
|
||||
"asyncio": asyncio,
|
||||
"_": None,
|
||||
"__builtins__": __builtins__,
|
||||
"__name__": "__main__",
|
||||
}
|
||||
|
||||
if ctx.channel.id in self.sessions:
|
||||
if self.sessions[ctx.channel.id]:
|
||||
await ctx.send(
|
||||
@@ -250,6 +233,9 @@ class Dev(commands.Cog):
|
||||
)
|
||||
return
|
||||
|
||||
env = self.get_environment(ctx)
|
||||
env["__builtins__"] = __builtins__
|
||||
env["_"] = None
|
||||
self.sessions[ctx.channel.id] = True
|
||||
await ctx.send(
|
||||
_(
|
||||
@@ -287,8 +273,7 @@ class Dev(commands.Cog):
|
||||
await ctx.send(self.get_syntax_error(e))
|
||||
continue
|
||||
|
||||
variables["message"] = response
|
||||
|
||||
env["message"] = response
|
||||
stdout = io.StringIO()
|
||||
|
||||
msg = ""
|
||||
@@ -296,9 +281,9 @@ class Dev(commands.Cog):
|
||||
try:
|
||||
with redirect_stdout(stdout):
|
||||
if executor is None:
|
||||
result = types.FunctionType(code, variables)()
|
||||
result = types.FunctionType(code, env)()
|
||||
else:
|
||||
result = executor(code, variables)
|
||||
result = executor(code, env)
|
||||
result = await self.maybe_await(result)
|
||||
except:
|
||||
value = stdout.getvalue()
|
||||
@@ -307,7 +292,7 @@ class Dev(commands.Cog):
|
||||
value = stdout.getvalue()
|
||||
if result is not None:
|
||||
msg = "{}{}".format(value, result)
|
||||
variables["_"] = result
|
||||
env["_"] = result
|
||||
elif value:
|
||||
msg = "{}".format(value)
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ async def is_allowed_by_hierarchy(
|
||||
if not await settings.guild(guild).respect_hierarchy():
|
||||
return True
|
||||
is_special = mod == guild.owner or await bot.is_owner(mod)
|
||||
return mod.top_role.position > user.top_role.position or is_special
|
||||
return mod.top_role > user.top_role or is_special
|
||||
|
||||
|
||||
async def is_mod_or_superior(
|
||||
|
||||
@@ -67,7 +67,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
def same_context(
|
||||
cls,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the message fits the described context.
|
||||
@@ -104,7 +104,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
def cancelled(
|
||||
cls,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the message is ``[p]cancel``.
|
||||
@@ -133,7 +133,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
def yes_or_no(
|
||||
cls,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the message is "yes"/"y" or "no"/"n".
|
||||
@@ -176,7 +176,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
def valid_int(
|
||||
cls,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response is an integer.
|
||||
@@ -216,7 +216,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
def valid_float(
|
||||
cls,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response is a float.
|
||||
@@ -256,7 +256,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
def positive(
|
||||
cls,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response is a positive number.
|
||||
@@ -492,7 +492,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
cls,
|
||||
value: str,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response is equal to the specified value.
|
||||
@@ -522,7 +522,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
cls,
|
||||
value: str,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response *as lowercase* is equal to the specified value.
|
||||
@@ -552,7 +552,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
cls,
|
||||
value: Union[int, float],
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response is less than the specified value.
|
||||
@@ -583,7 +583,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
cls,
|
||||
value: Union[int, float],
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response is greater than the specified value.
|
||||
@@ -614,7 +614,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
cls,
|
||||
length: int,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response's length is less than the specified length.
|
||||
@@ -644,7 +644,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
cls,
|
||||
length: int,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response's length is greater than the specified length.
|
||||
@@ -674,7 +674,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
cls,
|
||||
collection: Sequence[str],
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response is contained in the specified collection.
|
||||
@@ -718,7 +718,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
cls,
|
||||
collection: Sequence[str],
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Same as :meth:`contained_in`, but the response is set to lowercase before matching.
|
||||
@@ -759,7 +759,7 @@ class MessagePredicate(Callable[[discord.Message], bool]):
|
||||
cls,
|
||||
pattern: Union[Pattern[str], str],
|
||||
ctx: Optional[commands.Context] = None,
|
||||
channel: Optional[discord.TextChannel] = None,
|
||||
channel: Optional[Union[discord.TextChannel, discord.DMChannel]] = None,
|
||||
user: Optional[discord.abc.User] = None,
|
||||
) -> "MessagePredicate":
|
||||
"""Match if the response matches the specified regex pattern.
|
||||
|
||||
Reference in New Issue
Block a user