Skip to content

Commit

Permalink
[Mod] Move ignored guilds and channels to core (#3472)
Browse files Browse the repository at this point in the history
* Move ignored guilds and channels to core
Add caching for ignored guilds and channels
Add caching for whitelist and blacklist
Fix #3220
Add consume-rest for whitelist and blacklist commands to add multiple users or roles in one command

* Add ability to ignore channel categories

* black

* moveignorechannels should be owner only and cleanup changes

* add changelog entries

* address Feedback
  • Loading branch information
TrustyJAID committed Feb 15, 2020
1 parent 78192dc commit 74a3eba
Show file tree
Hide file tree
Showing 8 changed files with 458 additions and 239 deletions.
4 changes: 4 additions & 0 deletions changelog.d/3472.enhance.rst
@@ -0,0 +1,4 @@
Add caching for ignored channels/guilds.
Add caching for white/blacklist.
Add consume-rest for white/blacklist commands.
Allow ignoring channel categories.
1 change: 1 addition & 0 deletions changelog.d/mod/3472.enhance.rst
@@ -0,0 +1 @@
Move ignore commands and checks into core.
67 changes: 34 additions & 33 deletions redbot/cogs/mod/mod.py
Expand Up @@ -17,7 +17,7 @@

_ = T_ = Translator("Mod", __file__)

__version__ = "1.0.0"
__version__ = "1.1.0"


class CompositeMetaClass(type(commands.Cog), type(ABC)):
Expand Down Expand Up @@ -85,35 +85,36 @@ def cog_unload(self):

async def _maybe_update_config(self):
"""Maybe update `delete_delay` value set by Config prior to Mod 1.0.0."""
if await self.settings.version():
return
guild_dict = await self.settings.all_guilds()
for guild_id, info in guild_dict.items():
delete_repeats = info.get("delete_repeats", False)
if delete_repeats:
val = 3
else:
val = -1
await self.settings.guild(discord.Object(id=guild_id)).delete_repeats.set(val)
await self.settings.version.set(__version__)

# TODO: Move this to core.
# This would be in .movetocore , but the double-under name here makes that more trouble
async def bot_check(self, ctx):
"""Global check to see if a channel or server is ignored.
Any users who have permission to use the `ignore` or `unignore` commands
surpass the check.
"""
perms = ctx.channel.permissions_for(ctx.author)
surpass_ignore = (
isinstance(ctx.channel, discord.abc.PrivateChannel)
or perms.manage_guild
or await ctx.bot.is_owner(ctx.author)
or await ctx.bot.is_admin(ctx.author)
)
if surpass_ignore:
return True
guild_ignored = await self.settings.guild(ctx.guild).ignored()
chann_ignored = await self.settings.channel(ctx.channel).ignored()
return not (guild_ignored or chann_ignored and not perms.manage_channels)
if not await self.settings.version():
guild_dict = await self.settings.all_guilds()
for guild_id, info in guild_dict.items():
delete_repeats = info.get("delete_repeats", False)
if delete_repeats:
val = 3
else:
val = -1
await self.settings.guild(discord.Object(id=guild_id)).delete_repeats.set(val)
await self.settings.version.set("1.0.0") # set version of last update
if await self.settings.version() < "1.1.0":
prefixes = await self.bot.get_valid_prefixes()
msg = _(
"Ignored guilds and channels have been moved. "
"Please use `{prefix}moveignoredchannels` if "
"you were previously using these functions."
).format(prefix=prefixes[0])
await self.bot.send_to_owners(msg)
await self.settings.version.set(__version__)

@commands.command()
@commands.is_owner()
async def moveignoredchannels(self, ctx: commands.Context) -> None:
"""Move ignored channels and servers to core"""
all_guilds = await self.settings.all_guilds()
all_channels = await self.settings.all_channels()
for guild_id, settings in all_guilds.items():
await self.bot._config.guild_from_id(guild_id).ignored.set(settings["ignored"])
await self.settings.guild_from_id(guild_id).ignored.clear()
for channel_id, settings in all_channels.items():
await self.bot._config.channel_from_id(channel_id).ignored.set(settings["ignored"])
await self.settings.channel_fro_id(channel_id).clear()
await ctx.send(_("Ignored channels and guilds restored."))
81 changes: 0 additions & 81 deletions redbot/cogs/mod/movetocore.py
Expand Up @@ -47,84 +47,3 @@ async def _delete_helper(m):

await asyncio.sleep(delay)
await _delete_helper(message)

# When the below are moved to core, the global check in .modcore needs to be moved as well.
@commands.group()
@commands.guild_only()
@checks.admin_or_permissions(manage_channels=True)
async def ignore(self, ctx: commands.Context):
"""Add servers or channels to the ignore list."""
if ctx.invoked_subcommand is None:
await ctx.send(await self.count_ignored())

@ignore.command(name="channel")
async def ignore_channel(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""Ignore commands in the channel.
Defaults to the current channel.
"""
if not channel:
channel = ctx.channel
if not await self.settings.channel(channel).ignored():
await self.settings.channel(channel).ignored.set(True)
await ctx.send(_("Channel added to ignore list."))
else:
await ctx.send(_("Channel already in ignore list."))

@ignore.command(name="server", aliases=["guild"])
@checks.admin_or_permissions(manage_guild=True)
async def ignore_guild(self, ctx: commands.Context):
"""Ignore commands in this server."""
guild = ctx.guild
if not await self.settings.guild(guild).ignored():
await self.settings.guild(guild).ignored.set(True)
await ctx.send(_("This server has been added to the ignore list."))
else:
await ctx.send(_("This server is already being ignored."))

@commands.group()
@commands.guild_only()
@checks.admin_or_permissions(manage_channels=True)
async def unignore(self, ctx: commands.Context):
"""Remove servers or channels from the ignore list."""
if ctx.invoked_subcommand is None:
await ctx.send(await self.count_ignored())

@unignore.command(name="channel")
async def unignore_channel(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""Remove a channel from ignore the list.
Defaults to the current channel.
"""
if not channel:
channel = ctx.channel

if await self.settings.channel(channel).ignored():
await self.settings.channel(channel).ignored.set(False)
await ctx.send(_("Channel removed from ignore list."))
else:
await ctx.send(_("That channel is not in the ignore list."))

@unignore.command(name="server", aliases=["guild"])
@checks.admin_or_permissions(manage_guild=True)
async def unignore_guild(self, ctx: commands.Context):
"""Remove this server from the ignore list."""
guild = ctx.message.guild
if await self.settings.guild(guild).ignored():
await self.settings.guild(guild).ignored.set(False)
await ctx.send(_("This server has been removed from the ignore list."))
else:
await ctx.send(_("This server is not in the ignore list."))

async def count_ignored(self):
ch_count = 0
svr_count = 0
for guild in self.bot.guilds:
if not await self.settings.guild(guild).ignored():
for channel in guild.text_channels:
if await self.settings.channel(channel).ignored():
ch_count += 1
else:
svr_count += 1
msg = _("Currently ignoring:\n{} channels\n{} guilds\n").format(ch_count, svr_count)
return box(msg)
42 changes: 36 additions & 6 deletions redbot/core/bot.py
Expand Up @@ -38,7 +38,7 @@
from .events import init_events
from .global_checks import init_global_checks

from .settings_caches import PrefixManager
from .settings_caches import PrefixManager, IgnoreManager, WhitelistBlacklistManager

from .rpc import RPCMixin
from .utils import common_filters
Expand Down Expand Up @@ -118,13 +118,14 @@ def __init__(self, *args, cli_flags=None, bot_dir: Path = Path.cwd(), **kwargs):
admin_role=[],
mod_role=[],
embeds=None,
ignored=False,
use_bot_color=False,
fuzzy=False,
disabled_commands=[],
autoimmune_ids=[],
)

self._config.register_channel(embeds=None)
self._config.register_channel(embeds=None, ignored=False)
self._config.register_user(embeds=None)

self._config.init_custom(CUSTOM_GROUPS, 2)
Expand All @@ -133,6 +134,8 @@ def __init__(self, *args, cli_flags=None, bot_dir: Path = Path.cwd(), **kwargs):
self._config.init_custom(SHARED_API_TOKENS, 2)
self._config.register_custom(SHARED_API_TOKENS)
self._prefix_cache = PrefixManager(self._config, cli_flags)
self._ignored_cache = IgnoreManager(self._config)
self._whiteblacklist_cache = WhitelistBlacklistManager(self._config)

async def prefix_manager(bot, message) -> List[str]:
prefixes = await self._prefix_cache.get_prefixes(message.guild)
Expand Down Expand Up @@ -350,13 +353,13 @@ async def allowed_by_whitelist_blacklist(
if await self.is_owner(who):
return True

global_whitelist = await self._config.whitelist()
global_whitelist = await self._whiteblacklist_cache.get_whitelist()
if global_whitelist:
if who.id not in global_whitelist:
return False
else:
# blacklist is only used when whitelist doesn't exist.
global_blacklist = await self._config.blacklist()
global_blacklist = await self._whiteblacklist_cache.get_blacklist()
if who.id in global_blacklist:
return False

Expand All @@ -375,17 +378,44 @@ async def allowed_by_whitelist_blacklist(
# there is a silent failure potential, and role blacklist/whitelists will break.
ids = {i for i in (who.id, *(getattr(who, "_roles", []))) if i != guild.id}

guild_whitelist = await self._config.guild(guild).whitelist()
guild_whitelist = await self._whiteblacklist_cache.get_whitelist(guild)
if guild_whitelist:
if ids.isdisjoint(guild_whitelist):
return False
else:
guild_blacklist = await self._config.guild(guild).blacklist()
guild_blacklist = await self._whiteblacklist_cache.get_blacklist(guild)
if not ids.isdisjoint(guild_blacklist):
return False

return True

async def ignored_channel_or_guild(self, ctx: commands.Context) -> bool:
"""
This checks if the bot is meant to be ignoring commands in a channel or guild,
as considered by Red's whitelist and blacklist.
Parameters
----------
ctx : Context of where the command is being run.
Returns
-------
bool
`True` if commands are allowed in the channel, `False` otherwise
"""
perms = ctx.channel.permissions_for(ctx.author)
surpass_ignore = (
isinstance(ctx.channel, discord.abc.PrivateChannel)
or perms.manage_guild
or await ctx.bot.is_owner(ctx.author)
or await ctx.bot.is_admin(ctx.author)
)
if surpass_ignore:
return True
guild_ignored = await self._ignored_cache.get_ignored_guild(ctx.guild)
chann_ignored = await self._ignored_cache.get_ignored_channel(ctx.channel)
return not (guild_ignored or chann_ignored and not perms.manage_channels)

async def get_valid_prefixes(self, guild: Optional[discord.Guild] = None) -> List[str]:
"""
This gets the valid prefixes for a guild.
Expand Down

0 comments on commit 74a3eba

Please sign in to comment.