mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
Add per-command embed settings (embed_requested) (#4049)
* Add per-command embed settings * Update `[p]embedset showsettings` * Use command.qualified_name in `[p]embedset` commands * Fix the call to subcommand and simplify it * And I oversimplified this * Update end user messages to use 'guild' rather than 'server' * meh * This should be a named field * Add check for Embed Links perm to confuse users a bit less * Wrap this string in _() * Let's use a different exception then... * Let's clear the setting when we can in whole `[p]embedset` * Add the order of checking to help of `[p]embedset` * Add note about full evaluation order to subcommands
This commit is contained in:
parent
03d72dd5fa
commit
560e1dfc3d
@ -53,6 +53,7 @@ from .utils import common_filters, AsyncIter
|
||||
from .utils._internal_utils import send_to_owners_with_prefix_replaced
|
||||
|
||||
CUSTOM_GROUPS = "CUSTOM_GROUPS"
|
||||
COMMAND_SCOPE = "COMMAND"
|
||||
SHARED_API_TOKENS = "SHARED_API_TOKENS"
|
||||
|
||||
log = logging.getLogger("red")
|
||||
@ -155,6 +156,12 @@ class RedBase(
|
||||
self._config.init_custom(CUSTOM_GROUPS, 2)
|
||||
self._config.register_custom(CUSTOM_GROUPS)
|
||||
|
||||
# {COMMAND_NAME: {GUILD_ID: {...}}}
|
||||
# GUILD_ID=0 for global setting
|
||||
self._config.init_custom(COMMAND_SCOPE, 2)
|
||||
self._config.register_custom(COMMAND_SCOPE, embeds=None)
|
||||
# TODO: add cache for embed settings
|
||||
|
||||
self._config.init_custom(SHARED_API_TOKENS, 2)
|
||||
self._config.register_custom(SHARED_API_TOKENS)
|
||||
self._prefix_cache = PrefixManager(self._config, cli_flags)
|
||||
@ -1022,7 +1029,12 @@ class RedBase(
|
||||
ctx, help_for, from_help_command=from_help_command
|
||||
)
|
||||
|
||||
async def embed_requested(self, channel, user, command=None) -> bool:
|
||||
async def embed_requested(
|
||||
self,
|
||||
channel: Union[discord.abc.GuildChannel, discord.abc.PrivateChannel],
|
||||
user: discord.abc.User,
|
||||
command: Optional[commands.Command] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
Determine if an embed is requested for a response.
|
||||
|
||||
@ -1032,26 +1044,38 @@ class RedBase(
|
||||
The channel to check embed settings for.
|
||||
user : `discord.abc.User`
|
||||
The user to check embed settings for.
|
||||
command
|
||||
(Optional) the command ran.
|
||||
command : `commands.Command`, optional
|
||||
The command ran.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
:code:`True` if an embed is requested
|
||||
"""
|
||||
|
||||
async def get_command_setting(guild_id: int) -> Optional[bool]:
|
||||
if command is None:
|
||||
return None
|
||||
scope = self._config.custom(COMMAND_SCOPE, command.qualified_name, guild_id)
|
||||
return await scope.embeds()
|
||||
|
||||
if isinstance(channel, discord.abc.PrivateChannel):
|
||||
user_setting = await self._config.user(user).embeds()
|
||||
if user_setting is not None:
|
||||
if (user_setting := await self._config.user(user).embeds()) is not None:
|
||||
return user_setting
|
||||
else:
|
||||
channel_setting = await self._config.channel(channel).embeds()
|
||||
if channel_setting is not None:
|
||||
if (channel_setting := await self._config.channel(channel).embeds()) is not None:
|
||||
return channel_setting
|
||||
guild_setting = await self._config.guild(channel.guild).embeds()
|
||||
if guild_setting is not None:
|
||||
|
||||
if (command_setting := await get_command_setting(channel.guild.id)) is not None:
|
||||
return command_setting
|
||||
|
||||
if (guild_setting := await self._config.guild(channel.guild).embeds()) is not None:
|
||||
return guild_setting
|
||||
|
||||
# XXX: maybe this should be checked before guild setting?
|
||||
if (global_command_setting := await get_command_setting(0)) is not None:
|
||||
return global_command_setting
|
||||
|
||||
global_setting = await self._config.embeds()
|
||||
return global_setting
|
||||
|
||||
|
||||
@ -1049,22 +1049,62 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
use embeds as a response to a command (for
|
||||
commands that support it). The default is to
|
||||
use embeds.
|
||||
|
||||
The embed settings are checked until the first True/False in this order:
|
||||
- In guild context:
|
||||
1. Channel override ([p]embedset channel)
|
||||
2. Server command override ([p]embedset command server)
|
||||
3. Server override ([p]embedset server)
|
||||
4. Global command override ([p]embedset command global)
|
||||
5. Global setting ([p]embedset global)
|
||||
|
||||
- In DM context:
|
||||
1. User override ([p]embedset user)
|
||||
2. Global command override ([p]embedset command global)
|
||||
3. Global setting ([p]embedset global)
|
||||
"""
|
||||
|
||||
@embedset.command(name="showsettings")
|
||||
async def embedset_showsettings(self, ctx: commands.Context):
|
||||
async def embedset_showsettings(self, ctx: commands.Context, command_name: str = None) -> None:
|
||||
"""Show the current embed settings."""
|
||||
if command_name is not None:
|
||||
command_obj: Optional[commands.Command] = ctx.bot.get_command(command_name)
|
||||
if command_obj is None:
|
||||
await ctx.send(
|
||||
_("I couldn't find that command. Please note that it is case sensitive.")
|
||||
)
|
||||
return
|
||||
# qualified name might be different if alias was passed to this command
|
||||
command_name = command_obj.qualified_name
|
||||
|
||||
text = _("Embed settings:\n\n")
|
||||
global_default = await self.bot._config.embeds()
|
||||
text += _("Global default: {}\n").format(global_default)
|
||||
text += _("Global default: {value}\n").format(value=global_default)
|
||||
|
||||
if command_name is not None:
|
||||
scope = self.bot._config.custom("COMMAND", command_name, 0)
|
||||
global_command_setting = await scope.embeds()
|
||||
text += _("Global command setting for {command} command: {value}\n").format(
|
||||
command=inline(command_name), value=global_command_setting
|
||||
)
|
||||
|
||||
if ctx.guild:
|
||||
guild_setting = await self.bot._config.guild(ctx.guild).embeds()
|
||||
text += _("Guild setting: {}\n").format(guild_setting)
|
||||
text += _("Guild setting: {value}\n").format(value=guild_setting)
|
||||
|
||||
if command_name is not None:
|
||||
scope = self.bot._config.custom("COMMAND", command_name, ctx.guild.id)
|
||||
command_setting = await scope.embeds()
|
||||
text += _("Server command setting for {command} command: {value}\n").format(
|
||||
command=inline(command_name), value=command_setting
|
||||
)
|
||||
|
||||
if ctx.channel:
|
||||
channel_setting = await self.bot._config.channel(ctx.channel).embeds()
|
||||
text += _("Channel setting: {}\n").format(channel_setting)
|
||||
text += _("Channel setting: {value}\n").format(value=channel_setting)
|
||||
|
||||
user_setting = await self.bot._config.user(ctx.author).embeds()
|
||||
text += _("User setting: {}").format(user_setting)
|
||||
text += _("User setting: {value}").format(value=user_setting)
|
||||
await ctx.send(box(text))
|
||||
|
||||
@embedset.command(name="global")
|
||||
@ -1076,12 +1116,16 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
This is used as a fallback if the user
|
||||
or guild hasn't set a preference. The
|
||||
default is to use embeds.
|
||||
|
||||
To see full evaluation order of embed settings, run `[p]help embedset`
|
||||
"""
|
||||
current = await self.bot._config.embeds()
|
||||
await self.bot._config.embeds.set(not current)
|
||||
await ctx.send(
|
||||
_("Embeds are now {} by default.").format(_("disabled") if current else _("enabled"))
|
||||
)
|
||||
if current:
|
||||
await self.bot._config.embeds.set(False)
|
||||
await ctx.send(_("Embeds are now disabled by default."))
|
||||
else:
|
||||
await self.bot._config.embeds.clear()
|
||||
await ctx.send(_("Embeds are now enabled by default."))
|
||||
|
||||
@embedset.command(name="server", aliases=["guild"])
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
@ -1095,16 +1139,139 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
|
||||
If set, this is used instead of the global default
|
||||
to determine whether or not to use embeds. This is
|
||||
used for all commands done in a guild channel except
|
||||
for help commands.
|
||||
used for all commands done in a server channel.
|
||||
|
||||
To see full evaluation order of embed settings, run `[p]help embedset`
|
||||
"""
|
||||
await self.bot._config.guild(ctx.guild).embeds.set(enabled)
|
||||
if enabled is None:
|
||||
await self.bot._config.guild(ctx.guild).embeds.clear()
|
||||
await ctx.send(_("Embeds will now fall back to the global setting."))
|
||||
return
|
||||
|
||||
await self.bot._config.guild(ctx.guild).embeds.set(enabled)
|
||||
await ctx.send(
|
||||
_("Embeds are now enabled for this guild.")
|
||||
if enabled
|
||||
else _("Embeds are now disabled for this guild.")
|
||||
)
|
||||
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
@embedset.group(name="command", invoke_without_command=True)
|
||||
async def embedset_command(
|
||||
self, ctx: commands.Context, command_name: str, enabled: bool = None
|
||||
) -> None:
|
||||
"""
|
||||
Toggle the command's embed setting.
|
||||
|
||||
If you're the bot owner, this will change command's embed setting
|
||||
globally by default.
|
||||
|
||||
To see full evaluation order of embed settings, run `[p]help embedset`
|
||||
"""
|
||||
# Select the scope based on the author's privileges
|
||||
if await ctx.bot.is_owner(ctx.author):
|
||||
await self.embedset_command_global(ctx, command_name, enabled)
|
||||
else:
|
||||
await self.embedset_command_guild(ctx, command_name, enabled)
|
||||
|
||||
def _check_if_command_requires_embed_links(self, command_obj: commands.Command) -> None:
|
||||
for command in itertools.chain((command_obj,), command_obj.parents):
|
||||
if command_obj.requires.bot_perms.embed_links:
|
||||
# a slight abuse of this exception to save myself two lines later...
|
||||
raise commands.UserFeedbackCheckFailure(
|
||||
_(
|
||||
"The passed command requires Embed Links permission"
|
||||
" and therefore cannot be set to not use embeds."
|
||||
)
|
||||
)
|
||||
|
||||
@commands.is_owner()
|
||||
@embedset_command.command(name="global")
|
||||
async def embedset_command_global(
|
||||
self, ctx: commands.Context, command_name: str, enabled: bool = None
|
||||
):
|
||||
"""
|
||||
Toggle the commmand's embed setting.
|
||||
|
||||
If enabled is None, the setting will be unset and
|
||||
the global default will be used instead.
|
||||
|
||||
If set, this is used instead of the global default
|
||||
to determine whether or not to use embeds.
|
||||
|
||||
To see full evaluation order of embed settings, run `[p]help embedset`
|
||||
"""
|
||||
command_obj: Optional[commands.Command] = ctx.bot.get_command(command_name)
|
||||
if command_obj is None:
|
||||
await ctx.send(
|
||||
_("I couldn't find that command. Please note that it is case sensitive.")
|
||||
)
|
||||
return
|
||||
self._check_if_command_requires_embed_links(command_obj)
|
||||
# qualified name might be different if alias was passed to this command
|
||||
command_name = command_obj.qualified_name
|
||||
|
||||
if enabled is None:
|
||||
await self.bot._config.custom("COMMAND", command_name, 0).embeds.clear()
|
||||
await ctx.send(_("Embeds will now fall back to the global setting."))
|
||||
return
|
||||
|
||||
await self.bot._config.custom("COMMAND", command_name, 0).embeds.set(enabled)
|
||||
if enabled:
|
||||
await ctx.send(
|
||||
_("Embeds are now enabled for {command_name} command.").format(
|
||||
command_name=inline(command_name)
|
||||
)
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
_("Embeds are now {} for this guild.").format(
|
||||
_("enabled") if enabled else _("disabled")
|
||||
_("Embeds are now disabled for {command_name} command.").format(
|
||||
command_name=inline(command_name)
|
||||
)
|
||||
)
|
||||
|
||||
@commands.guild_only()
|
||||
@embedset_command.command(name="server", aliases=["guild"])
|
||||
async def embedset_command_guild(
|
||||
self, ctx: commands.GuildContext, command_name: str, enabled: bool = None
|
||||
):
|
||||
"""
|
||||
Toggle the commmand's embed setting.
|
||||
|
||||
If enabled is None, the setting will be unset and
|
||||
the server default will be used instead.
|
||||
|
||||
If set, this is used instead of the server default
|
||||
to determine whether or not to use embeds.
|
||||
|
||||
To see full evaluation order of embed settings, run `[p]help embedset`
|
||||
"""
|
||||
command_obj: Optional[commands.Command] = ctx.bot.get_command(command_name)
|
||||
if command_obj is None:
|
||||
await ctx.send(
|
||||
_("I couldn't find that command. Please note that it is case sensitive.")
|
||||
)
|
||||
return
|
||||
self._check_if_command_requires_embed_links(command_obj)
|
||||
# qualified name might be different if alias was passed to this command
|
||||
command_name = command_obj.qualified_name
|
||||
|
||||
if enabled is None:
|
||||
await self.bot._config.custom("COMMAND", command_name, ctx.guild.id).embeds.clear()
|
||||
await ctx.send(_("Embeds will now fall back to the server setting."))
|
||||
return
|
||||
|
||||
await self.bot._config.custom("COMMAND", command_name, ctx.guild.id).embeds.set(enabled)
|
||||
if enabled:
|
||||
await ctx.send(
|
||||
_("Embeds are now enabled for {command_name} command.").format(
|
||||
command_name=inline(command_name)
|
||||
)
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
_("Embeds are now disabled for {command_name} command.").format(
|
||||
command_name=inline(command_name)
|
||||
)
|
||||
)
|
||||
|
||||
@ -1118,20 +1285,23 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
If enabled is None, the setting will be unset and
|
||||
the guild default will be used instead.
|
||||
|
||||
If set, this is used instead of the guild default
|
||||
If set, this is used instead of the guild and command default
|
||||
to determine whether or not to use embeds. This is
|
||||
used for all commands done in a channel except
|
||||
for help commands.
|
||||
used for all commands done in a channel.
|
||||
|
||||
To see full evaluation order of embed settings, run `[p]help embedset`
|
||||
"""
|
||||
await self.bot._config.channel(ctx.channel).embeds.set(enabled)
|
||||
if enabled is None:
|
||||
await self.bot._config.channel(ctx.channel).embeds.clear()
|
||||
await ctx.send(_("Embeds will now fall back to the global setting."))
|
||||
else:
|
||||
await ctx.send(
|
||||
_("Embeds are now {} for this channel.").format(
|
||||
_("enabled") if enabled else _("disabled")
|
||||
)
|
||||
return
|
||||
|
||||
await self.bot._config.channel(ctx.channel).embeds.set(enabled)
|
||||
await ctx.send(
|
||||
_("Embeds are now {} for this channel.").format(
|
||||
_("enabled") if enabled else _("disabled")
|
||||
)
|
||||
)
|
||||
|
||||
@embedset.command(name="user")
|
||||
async def embedset_user(self, ctx: commands.Context, enabled: bool = None):
|
||||
@ -1144,16 +1314,19 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
If set, this is used instead of the global default
|
||||
to determine whether or not to use embeds. This is
|
||||
used for all commands executed in a DM with the bot.
|
||||
|
||||
To see full evaluation order of embed settings, run `[p]help embedset`
|
||||
"""
|
||||
await self.bot._config.user(ctx.author).embeds.set(enabled)
|
||||
if enabled is None:
|
||||
await self.bot._config.user(ctx.author).embeds.clear()
|
||||
await ctx.send(_("Embeds will now fall back to the global setting."))
|
||||
else:
|
||||
await ctx.send(
|
||||
_("Embeds are now enabled for you in DMs.")
|
||||
if enabled
|
||||
else _("Embeds are now disabled for you in DMs.")
|
||||
)
|
||||
|
||||
await self.bot._config.user(ctx.author).embeds.set(enabled)
|
||||
await ctx.send(
|
||||
_("Embeds are now enabled for you in DMs.")
|
||||
if enabled
|
||||
else _("Embeds are now disabled for you in DMs.")
|
||||
)
|
||||
|
||||
@commands.command()
|
||||
@checks.is_owner()
|
||||
@ -3268,7 +3441,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
@command_disable.command(name="global")
|
||||
async def command_disable_global(self, ctx: commands.Context, *, command: str):
|
||||
"""Disable a command globally."""
|
||||
command_obj: commands.Command = ctx.bot.get_command(command)
|
||||
command_obj: Optional[commands.Command] = ctx.bot.get_command(command)
|
||||
if command_obj is None:
|
||||
await ctx.send(
|
||||
_("I couldn't find that command. Please note that it is case sensitive.")
|
||||
@ -3302,7 +3475,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
@command_disable.command(name="server", aliases=["guild"])
|
||||
async def command_disable_guild(self, ctx: commands.Context, *, command: str):
|
||||
"""Disable a command in this server only."""
|
||||
command_obj: commands.Command = ctx.bot.get_command(command)
|
||||
command_obj: Optional[commands.Command] = ctx.bot.get_command(command)
|
||||
if command_obj is None:
|
||||
await ctx.send(
|
||||
_("I couldn't find that command. Please note that it is case sensitive.")
|
||||
@ -3352,7 +3525,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
@command_enable.command(name="global")
|
||||
async def command_enable_global(self, ctx: commands.Context, *, command: str):
|
||||
"""Enable a command globally."""
|
||||
command_obj: commands.Command = ctx.bot.get_command(command)
|
||||
command_obj: Optional[commands.Command] = ctx.bot.get_command(command)
|
||||
if command_obj is None:
|
||||
await ctx.send(
|
||||
_("I couldn't find that command. Please note that it is case sensitive.")
|
||||
@ -3374,7 +3547,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
||||
@command_enable.command(name="server", aliases=["guild"])
|
||||
async def command_enable_guild(self, ctx: commands.Context, *, command: str):
|
||||
"""Enable a command in this server."""
|
||||
command_obj: commands.Command = ctx.bot.get_command(command)
|
||||
command_obj: Optional[commands.Command] = ctx.bot.get_command(command)
|
||||
if command_obj is None:
|
||||
await ctx.send(
|
||||
_("I couldn't find that command. Please note that it is case sensitive.")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user